Update clang to 91430.
This commit is contained in:
parent
1569ce6868
commit
34d02d0b37
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=200583
@ -17,7 +17,7 @@ Creating and using a PTH file for performance measurement (use a release-asserts
|
||||
build).
|
||||
|
||||
$ clang -ccc-pch-is-pth -x objective-c-header INPUTS/Cocoa_h.m -o /tmp/tokencache
|
||||
$ clang-cc -token-cache /tmp/tokencache INPUTS/Cocoa_h.m
|
||||
$ clang -cc1 -token-cache /tmp/tokencache INPUTS/Cocoa_h.m
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
|
1
TODO.txt
1
TODO.txt
@ -65,7 +65,6 @@ More ideas for code modification hints:
|
||||
- If no member of a given name is found in a class/struct, search through the names of entities that do exist in the class and suggest the closest candidate. e.g., if I write "DS.setTypeSpecType", it would suggest "DS.SetTypeSpecType" (edit distance = 1).
|
||||
- If a class member is defined out-of-line but isn't in the class declaration (and there are no close matches!), provide the option to add an in-class declaration.
|
||||
- Fix-it hints for the inclusion of headers when needed for particular features (e.g., <typeinfo> for typeid)
|
||||
- Change "foo.bar" to "foo->bar" when "foo" is a pointer.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
|
@ -37,13 +37,14 @@
|
||||
1A6B6CD410693FC900BB4A8F /* CodeCompleteConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */; };
|
||||
1A6B6CD510693FC900BB4A8F /* SemaCodeComplete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */; };
|
||||
1A6B6E9A1069833600BB4A8F /* CGExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */; };
|
||||
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6C01F6108128710072DEE4 /* CGRtti.cpp */; };
|
||||
1A6C01F7108128710072DEE4 /* CGRTTI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6C01F6108128710072DEE4 /* CGRTTI.cpp */; };
|
||||
1A6FE7090FD6F85800E00CA9 /* CGTemporaries.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */; };
|
||||
1A701B640F7C8FE400FEC4D1 /* SemaAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A701B630F7C8FE400FEC4D1 /* SemaAccess.cpp */; };
|
||||
1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; };
|
||||
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A81AA18108144F40094E50B /* CGVtable.cpp */; };
|
||||
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
|
||||
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
|
||||
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; };
|
||||
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
|
||||
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
|
||||
1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795110A90C6100741BBA /* TypePrinter.cpp */; };
|
||||
@ -53,7 +54,6 @@
|
||||
1AE4EE3E103B89ED00888A23 /* StmtProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */; };
|
||||
1AE4EE40103B8A0A00888A23 /* TargetABIInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */; };
|
||||
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */; };
|
||||
1AFEF4070F8A6B2300476F2B /* clang-cc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */; };
|
||||
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
|
||||
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
|
||||
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
|
||||
@ -279,6 +279,7 @@
|
||||
DEF7D9F70C9C8B1A0001F598 /* Rewriter.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEF7D9F60C9C8B1A0001F598 /* Rewriter.h */; };
|
||||
DEF7D9F90C9C8B1D0001F598 /* Rewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF7D9F80C9C8B1D0001F598 /* Rewriter.cpp */; };
|
||||
DEFFECA70DB1546600B4E7C3 /* DeltaTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEFFECA60DB1546600B4E7C3 /* DeltaTree.cpp */; };
|
||||
E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E16B523410D30B2400430AC9 /* cc1_main.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@ -379,7 +380,7 @@
|
||||
1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaCodeComplete.cpp; path = lib/Sema/SemaCodeComplete.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A6B6CD310693FC900BB4A8F /* SemaTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = SemaTemplate.h; path = lib/Sema/SemaTemplate.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprCXX.cpp; path = lib/CodeGen/CGExprCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A6C01F6108128710072DEE4 /* CGRtti.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRtti.cpp; path = lib/CodeGen/CGRtti.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A6C01F6108128710072DEE4 /* CGRTTI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRTTI.cpp; path = lib/CodeGen/CGRTTI.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGTemporaries.cpp; path = lib/CodeGen/CGTemporaries.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A7019E90F79BC1100FEC4D1 /* DiagnosticAnalysisKinds.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticAnalysisKinds.td; sourceTree = "<group>"; };
|
||||
1A7019EA0F79BC1100FEC4D1 /* DiagnosticASTKinds.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticASTKinds.td; sourceTree = "<group>"; };
|
||||
@ -396,6 +397,7 @@
|
||||
1A81AA5D108278A20094E50B /* CGVtable.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGVtable.h; path = lib/CodeGen/CGVtable.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
|
||||
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
|
||||
1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDeclCXX.cpp; path = lib/CodeGen/CGDeclCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
@ -408,7 +410,6 @@
|
||||
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetABIInfo.cpp; path = lib/CodeGen/TargetABIInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGException.cpp; path = lib/CodeGen/CGException.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = "clang-cc.cpp"; path = "tools/clang-cc/clang-cc.cpp"; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckObjCInstMethSignature.cpp; path = lib/Analysis/CheckObjCInstMethSignature.cpp; sourceTree = "<group>"; };
|
||||
@ -807,6 +808,7 @@
|
||||
DEF7D9F80C9C8B1D0001F598 /* Rewriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Rewriter.cpp; path = lib/Rewrite/Rewriter.cpp; sourceTree = "<group>"; };
|
||||
DEFFECA30DB093D100B4E7C3 /* DeltaTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeltaTree.h; path = clang/Rewrite/DeltaTree.h; sourceTree = "<group>"; };
|
||||
DEFFECA60DB1546600B4E7C3 /* DeltaTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeltaTree.cpp; path = lib/Rewrite/DeltaTree.cpp; sourceTree = "<group>"; };
|
||||
E16B523410D30B2400430AC9 /* cc1_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cc1_main.cpp; path = tools/driver/cc1_main.cpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -1268,13 +1270,14 @@
|
||||
1A4C41BE105B4C0B0047B5E7 /* CGClass.cpp */,
|
||||
1A5D5E570E5E81010023C059 /* CGCXX.cpp */,
|
||||
1A649E1E0F9599DA005B965E /* CGCXX.h */,
|
||||
1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */,
|
||||
35A3E7000DD3874400757F74 /* CGDebugInfo.cpp */,
|
||||
35A3E7010DD3874400757F74 /* CGDebugInfo.h */,
|
||||
DE4264FB0C113592005A861D /* CGDecl.cpp */,
|
||||
1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */,
|
||||
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */,
|
||||
DE4772FB0C10EAEC002239E8 /* CGExpr.cpp */,
|
||||
DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */,
|
||||
1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */,
|
||||
DE224FF70C7AA98800D370A5 /* CGExprComplex.cpp */,
|
||||
1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */,
|
||||
DE22526F0C7E82D000D370A5 /* CGExprScalar.cpp */,
|
||||
@ -1284,7 +1287,7 @@
|
||||
3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */,
|
||||
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */,
|
||||
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */,
|
||||
1A6C01F6108128710072DEE4 /* CGRtti.cpp */,
|
||||
1A6C01F6108128710072DEE4 /* CGRTTI.cpp */,
|
||||
DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
|
||||
1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */,
|
||||
35475B230E7997680000BFE4 /* CGValue.h */,
|
||||
@ -1539,23 +1542,15 @@
|
||||
90F9EFA8104ABDC400D09A15 /* c-index-test */,
|
||||
9012911E104812DA0083456D /* CIndex */,
|
||||
90FD6DB4103D9763005F5B73 /* index-test */,
|
||||
DEDFE6200F7B3AE90035BD10 /* clang-cc */,
|
||||
DEDFE6210F7B3AF10035BD10 /* clang */,
|
||||
);
|
||||
name = Tools;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DEDFE6200F7B3AE90035BD10 /* clang-cc */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */,
|
||||
);
|
||||
name = "clang-cc";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DEDFE6210F7B3AF10035BD10 /* clang */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E16B523410D30B2400430AC9 /* cc1_main.cpp */,
|
||||
DEDFE6450F7B3B4E0035BD10 /* driver.cpp */,
|
||||
);
|
||||
name = clang;
|
||||
@ -1872,7 +1867,6 @@
|
||||
1A701B640F7C8FE400FEC4D1 /* SemaAccess.cpp in Sources */,
|
||||
906BF4B00F83BA2E001071FA /* ConvertUTF.c in Sources */,
|
||||
DEDFF8880F848CF80035BD10 /* TemplateName.cpp in Sources */,
|
||||
1AFEF4070F8A6B2300476F2B /* clang-cc.cpp in Sources */,
|
||||
DEF165710F8FB34D0098507F /* PCHWriter.cpp in Sources */,
|
||||
DEF165750F8FB3510098507F /* PCHReader.cpp in Sources */,
|
||||
DEF168400F9548DC0098507F /* FixItRewriter.cpp in Sources */,
|
||||
@ -1927,12 +1921,14 @@
|
||||
1A6B6CD510693FC900BB4A8F /* SemaCodeComplete.cpp in Sources */,
|
||||
1A6B6E9A1069833600BB4A8F /* CGExprCXX.cpp in Sources */,
|
||||
1A535ED9107BC45E000C3AE7 /* CXXInheritance.cpp in Sources */,
|
||||
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */,
|
||||
1A6C01F7108128710072DEE4 /* CGRTTI.cpp in Sources */,
|
||||
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */,
|
||||
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */,
|
||||
1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */,
|
||||
1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */,
|
||||
1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */,
|
||||
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */,
|
||||
E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -292,7 +292,7 @@ would be rewritten to be:
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
int captured_i;
|
||||
} i = { NULL, &i, 0, sizeof(struct _block_byref_i), 11;
|
||||
} i = { NULL, &i, 0, sizeof(struct _block_byref_i), 11 };
|
||||
|
||||
i.forwarding->captured_i = 11;
|
||||
|
||||
|
@ -23,6 +23,11 @@ td {
|
||||
<li><a href="#has_include">Include File Checking Macros</a></li>
|
||||
<li><a href="#builtinmacros">Builtin Macros</a></li>
|
||||
<li><a href="#vectors">Vectors and Extended Vectors</a></li>
|
||||
<li><a href="#checking_language_features">Checks for Standard Language Features</a></li>
|
||||
<ul>
|
||||
<li><a href="#cxx_exceptions">C++ exceptions</a></li>
|
||||
<li><a href="#cxx_rtti">C++ RTTI</a></li>
|
||||
</ul>
|
||||
<li><a href="#blocks">Blocks</a></li>
|
||||
<li><a href="#overloading-in-c">Function Overloading in C</a></li>
|
||||
<li><a href="#builtins">Builtin Functions</a>
|
||||
@ -193,6 +198,23 @@ href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p>
|
||||
|
||||
<p>Query for this feature with __has_feature(attribute_ext_vector_type).</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="checking_language_features">Checks for Standard Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The <tt>__has_feature</tt> macro can be used to query if certain standard language features are
|
||||
enabled. Those features are listed here.</p>
|
||||
|
||||
<h3 id="cxx_exceptions">C++ exceptions</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_exceptions)</tt> to determine if C++ exceptions have been enabled. For
|
||||
example, compiling code with <tt>-fexceptions</tt> enables C++ exceptions.</p>
|
||||
|
||||
<h3 id="cxx_rtti">C++ RTTI</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_rtti)</tt> to determine if C++ RTTI has been enabled. For example,
|
||||
compiling code with <tt>-fno-rtti</tt> disables the use of RTTI.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="blocks">Blocks</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
@ -26,7 +26,7 @@
|
||||
<p><b>Table of Contents</b></p>
|
||||
<ul>
|
||||
<li><a href="#usage">Using Precompiled Headers with
|
||||
<tt>clang-cc</tt></a></li>
|
||||
<tt>clang</tt></a></li>
|
||||
<li><a href="#philosophy">Design Philosophy</a></li>
|
||||
<li><a href="#contents">Precompiled Header Contents</a>
|
||||
<ul>
|
||||
@ -44,15 +44,15 @@
|
||||
Points</a></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="usage">Using Precompiled Headers with <tt>clang-cc</tt></h2>
|
||||
<h2 id="usage">Using Precompiled Headers with <tt>clang</tt></h2>
|
||||
|
||||
<p>The low-level Clang compiler, <tt>clang-cc</tt>, supports two command
|
||||
line options for generating and using PCH files.<p>
|
||||
<p>The Clang compiler frontend, <tt>clang -cc1</tt>, supports two command line
|
||||
options for generating and using PCH files.<p>
|
||||
|
||||
<p>To generate PCH files using <tt>clang-cc</tt>, use the option
|
||||
<p>To generate PCH files using <tt>clang -cc1</tt>, use the option
|
||||
<b><tt>-emit-pch</tt></b>:
|
||||
|
||||
<pre> $ clang-cc test.h -emit-pch -o test.h.pch </pre>
|
||||
<pre> $ clang -cc1 test.h -emit-pch -o test.h.pch </pre>
|
||||
|
||||
<p>This option is transparently used by <tt>clang</tt> when generating
|
||||
PCH files. The resulting PCH file contains the serialized form of the
|
||||
@ -61,7 +61,7 @@ semantic analysis. The PCH file can then be used as a prefix header
|
||||
with the <b><tt>-include-pch</tt></b> option:</p>
|
||||
|
||||
<pre>
|
||||
$ clang-cc -include-pch test.h.pch test.c -o test.s
|
||||
$ clang -cc1 -include-pch test.h.pch test.c -o test.s
|
||||
</pre>
|
||||
|
||||
<h2 id="philosophy">Design Philosophy</h2>
|
||||
|
@ -23,38 +23,38 @@ implementation. If you are interested in the end-user view, please see the
|
||||
<a href="UsersManual.html#precompiledheaders">User's Manual</a>.</p>
|
||||
|
||||
|
||||
<h2>Using Pretokenized Headers with <tt>clang-cc</tt> (Low-level Interface)</h2>
|
||||
<h2>Using Pretokenized Headers with <tt>clang</tt> (Low-level Interface)</h2>
|
||||
|
||||
<p>The low-level Clang compiler tool, <tt>clang-cc</tt>, supports three command
|
||||
line options for generating and using PTH files.<p>
|
||||
<p>The Clang compiler frontend, <tt>clang -cc1</tt>, supports three command line
|
||||
options for generating and using PTH files.<p>
|
||||
|
||||
<p>To generate PTH files using <tt>clang-cc</tt>, use the option
|
||||
<p>To generate PTH files using <tt>clang -cc1</tt>, use the option
|
||||
<b><tt>-emit-pth</tt></b>:
|
||||
|
||||
<pre> $ clang-cc test.h -emit-pth -o test.h.pth </pre>
|
||||
<pre> $ clang -cc1 test.h -emit-pth -o test.h.pth </pre>
|
||||
|
||||
<p>This option is transparently used by <tt>clang</tt> when generating PTH
|
||||
files. Similarly, PTH files can be used as prefix headers using the
|
||||
<b><tt>-include-pth</tt></b> option:</p>
|
||||
|
||||
<pre>
|
||||
$ clang-cc -include-pth test.h.pth test.c -o test.s
|
||||
$ clang -cc1 -include-pth test.h.pth test.c -o test.s
|
||||
</pre>
|
||||
|
||||
<p>Alternatively, Clang's PTH files can be used as a raw "token-cache"
|
||||
(or "content" cache) of the source included by the original header
|
||||
file. This means that the contents of the PTH file are searched as substitutes
|
||||
for <em>any</em> source files that are used by <tt>clang-cc</tt> to process a
|
||||
for <em>any</em> source files that are used by <tt>clang -cc1</tt> to process a
|
||||
source file. This is done by specifying the <b><tt>-token-cache</tt></b>
|
||||
option:</p>
|
||||
|
||||
<pre>
|
||||
$ cat test.h
|
||||
#include <stdio.h>
|
||||
$ clang-cc -emit-pth test.h -o test.h.pth
|
||||
$ clang -cc1 -emit-pth test.h -o test.h.pth
|
||||
$ cat test.c
|
||||
#include "test.h"
|
||||
$ clang-cc test.c -o test -token-cache test.h.pth
|
||||
$ clang -cc1 test.c -o test -token-cache test.h.pth
|
||||
</pre>
|
||||
|
||||
<p>In this example the contents of <tt>stdio.h</tt> (and the files it includes)
|
||||
@ -117,7 +117,7 @@ PTH file needs to be generated during a build instead of several.</p></li>
|
||||
<li><p><b>Reduced memory pressure</b>: Similar to GCC,
|
||||
Clang reads PTH files via the use of memory mapping (i.e., <tt>mmap</tt>).
|
||||
Clang, however, memory maps PTH files as read-only, meaning that multiple
|
||||
invocations of <tt>clang-cc</tt> can share the same pages in memory from a
|
||||
invocations of <tt>clang -cc1</tt> can share the same pages in memory from a
|
||||
memory-mapped PTH file. In comparison, GCC also memory maps its PCH files but
|
||||
also modifies those pages in memory, incurring the copy-on-write costs. The
|
||||
read-only nature of PTH can greatly reduce memory pressure for builds involving
|
||||
@ -160,7 +160,7 @@ optimizations to speed up the processing of header files:</p>
|
||||
<ul>
|
||||
|
||||
<li><p><em><tt>stat</tt> caching</em>: PTH files cache information obtained via
|
||||
calls to <tt>stat</tt> that <tt>clang-cc</tt> uses to resolve which files are
|
||||
calls to <tt>stat</tt> that <tt>clang -cc1</tt> uses to resolve which files are
|
||||
included by <tt>#include</tt> directives. This greatly reduces the overhead
|
||||
involved in context-switching to the kernel to resolve included files.</p></li>
|
||||
|
||||
|
@ -40,6 +40,7 @@ td {
|
||||
<li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li>
|
||||
</ul>
|
||||
<li><a href="#precompiledheaders">Precompiled Headers</a></li>
|
||||
<li><a href="#codegen">Controlling Code Generation</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#c">C Language Features</a>
|
||||
@ -562,6 +563,29 @@ at the time of PCH use requires one of the PCH optimizations,
|
||||
<code>stat()</code> caching, to be disabled. However, this change is only
|
||||
likely to affect PCH files that reference a large number of headers.</p>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="codegen">Controlling Code Generation</h3>
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
|
||||
<p>Clang provides a number of ways to control code generation. The options are listed below.</p>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fcatch-undefined-behavior"><b>-fcatch-undefined-behavior</b>: Turn
|
||||
on runtime code generation to check for undefined behavior.</dt>
|
||||
|
||||
<dd>This option, which defaults to off, controls whether or not Clang
|
||||
adds runtime checks for undefined runtime behavior. If the check fails,
|
||||
<tt>__builtin_trap()</tt> is used to indicate failure.
|
||||
The checks are:
|
||||
<p>
|
||||
<li>Subscripting where the static type of one operand is decayed from an
|
||||
array type and the other operand is greater than the size of the array or
|
||||
less than zero.</li>
|
||||
<li>Shift operators where the amount shifted is greater or equal to the
|
||||
promoted bit-width of the left-hand-side or less than zero.</li>
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="c">C Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
@ -211,8 +211,8 @@ void bar_func(void) {
|
||||
You first get AST files out of <code>t1.c</code> and <code>t2.c</code>:
|
||||
|
||||
<pre class="code_example">
|
||||
$ clang-cc -emit-pch t1.c -o t1.ast
|
||||
$ clang-cc -emit-pch t2.c -o t2.ast
|
||||
$ clang -emit-ast t1.c -o t1.ast
|
||||
$ clang -emit-ast t2.c -o t2.ast
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
@ -104,6 +104,34 @@ enum CXCursorKind {
|
||||
CXCursor_LastInvalid = 72
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Provides the contents of a file that has not yet been saved to disk.
|
||||
*
|
||||
* Each CXUnsavedFile instance provides the name of a file on the
|
||||
* system along with the current contents of that file that have not
|
||||
* yet been saved to disk.
|
||||
*/
|
||||
struct CXUnsavedFile {
|
||||
/**
|
||||
* \brief The file whose contents have not yet been saved.
|
||||
*
|
||||
* This file must already exist in the file system.
|
||||
*/
|
||||
const char *Filename;
|
||||
|
||||
/**
|
||||
* \brief A null-terminated buffer containing the unsaved contents
|
||||
* of this file.
|
||||
*/
|
||||
const char *Contents;
|
||||
|
||||
/**
|
||||
* \brief The length of the unsaved contents of this buffer, not
|
||||
* counting the NULL at the end of the buffer.
|
||||
*/
|
||||
unsigned long Length;
|
||||
};
|
||||
|
||||
/* A cursor into the CXTranslationUnit. */
|
||||
|
||||
typedef struct {
|
||||
@ -174,8 +202,22 @@ CINDEX_LINKAGE void clang_disposeString(CXString string);
|
||||
*/
|
||||
CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
|
||||
int displayDiagnostics);
|
||||
CINDEX_LINKAGE void clang_disposeIndex(CXIndex);
|
||||
CINDEX_LINKAGE CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
|
||||
CINDEX_LINKAGE void clang_disposeIndex(CXIndex index);
|
||||
CINDEX_LINKAGE CXString
|
||||
clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
|
||||
|
||||
/*
|
||||
* \brief Request that AST's be generated external for API calls which parse
|
||||
* source code on the fly, e.g. \see createTranslationUnitFromSourceFile.
|
||||
*
|
||||
* Note: This is for debugging purposes only, and may be removed at a later
|
||||
* date.
|
||||
*
|
||||
* \param index - The index to update.
|
||||
* \param value - The new flag value.
|
||||
*/
|
||||
CINDEX_LINKAGE void clang_setUseExternalASTGeneration(CXIndex index,
|
||||
int value);
|
||||
|
||||
/*
|
||||
* \brief Create a translation unit from an AST file (-emit-ast).
|
||||
@ -183,6 +225,7 @@ CINDEX_LINKAGE CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUni
|
||||
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
|
||||
CXIndex, const char *ast_filename
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Destroy the specified CXTranslationUnit object.
|
||||
*/
|
||||
@ -192,20 +235,25 @@ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
|
||||
* \brief Return the CXTranslationUnit for a given source file and the provided
|
||||
* command line arguments one would pass to the compiler.
|
||||
*
|
||||
* Note: The 'source_filename' argument is optional. If the caller provides a NULL pointer,
|
||||
* the name of the source file is expected to reside in the specified command line arguments.
|
||||
* Note: The 'source_filename' argument is optional. If the caller provides a
|
||||
* NULL pointer, the name of the source file is expected to reside in the
|
||||
* specified command line arguments.
|
||||
*
|
||||
* Note: When encountered in 'clang_command_line_args', the following options are ignored:
|
||||
* Note: When encountered in 'clang_command_line_args', the following options
|
||||
* are ignored:
|
||||
*
|
||||
* '-c'
|
||||
* '-emit-ast'
|
||||
* '-fsyntax-only'
|
||||
* '-o <output file>' (both '-o' and '<output file>' are ignored)
|
||||
*
|
||||
*
|
||||
* \param source_filename - The name of the source file to load, or NULL if the
|
||||
* source file is included in clang_command_line_args.
|
||||
*/
|
||||
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
|
||||
CXIndex CIdx,
|
||||
const char *source_filename /* specify NULL if the source file is in clang_command_line_args */,
|
||||
CXIndex CIdx,
|
||||
const char *source_filename,
|
||||
int num_clang_command_line_args,
|
||||
const char **clang_command_line_args
|
||||
);
|
||||
@ -225,13 +273,14 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
|
||||
}
|
||||
static void usage {
|
||||
clang_loadTranslationUnit(CXTranslationUnit, printObjCInterfaceNames);
|
||||
}
|
||||
}
|
||||
*/
|
||||
typedef void *CXClientData;
|
||||
typedef void (*CXTranslationUnitIterator)(CXTranslationUnit, CXCursor,
|
||||
CXClientData);
|
||||
CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
|
||||
CXClientData);
|
||||
CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit,
|
||||
CXTranslationUnitIterator,
|
||||
CXClientData);
|
||||
|
||||
/*
|
||||
Usage: clang_loadDeclaration(). Will load the declaration, issuing a
|
||||
@ -292,8 +341,9 @@ CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
|
||||
Usage: clang_getCursor() will translate a source/line/column position
|
||||
into an AST cursor (to derive semantic information from the source code).
|
||||
*/
|
||||
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
|
||||
unsigned line, unsigned column);
|
||||
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit,
|
||||
const char *source_name,
|
||||
unsigned line, unsigned column);
|
||||
|
||||
CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
|
||||
|
||||
@ -606,11 +656,11 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
|
||||
* \param CIdx the \c CXIndex instance that will be used to perform code
|
||||
* completion.
|
||||
*
|
||||
* \param source_filename the name of the source file that should be parsed
|
||||
* to perform code-completion. This source file must be the same as or
|
||||
* include the filename described by \p complete_filename, or no code-completion
|
||||
* results will be produced. NOTE: One can also specify NULL for this argument if
|
||||
* the source file is included in command_line_args.
|
||||
* \param source_filename the name of the source file that should be parsed to
|
||||
* perform code-completion. This source file must be the same as or include the
|
||||
* filename described by \p complete_filename, or no code-completion results
|
||||
* will be produced. NOTE: One can also specify NULL for this argument if the
|
||||
* source file is included in command_line_args.
|
||||
*
|
||||
* \param num_command_line_args the number of command-line arguments stored in
|
||||
* \p command_line_args.
|
||||
@ -621,6 +671,13 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
|
||||
* includes, etc., but should not include any information specific to
|
||||
* code completion.
|
||||
*
|
||||
* \param num_unsaved_files the number of unsaved file entries in \p
|
||||
* unsaved_files.
|
||||
*
|
||||
* \param unsaved_files the files that have not yet been saved to disk
|
||||
* but may be required for code completion, including the contents of
|
||||
* those files.
|
||||
*
|
||||
* \param complete_filename the name of the source file where code completion
|
||||
* should be performed. In many cases, this name will be the same as the
|
||||
* source filename. However, the completion filename may also be a file
|
||||
@ -643,6 +700,8 @@ CINDEX_LINKAGE void clang_codeComplete(CXIndex CIdx,
|
||||
const char *source_filename,
|
||||
int num_command_line_args,
|
||||
const char **command_line_args,
|
||||
unsigned num_unsaved_files,
|
||||
struct CXUnsavedFile *unsaved_files,
|
||||
const char *complete_filename,
|
||||
unsigned complete_line,
|
||||
unsigned complete_column,
|
||||
|
@ -45,6 +45,8 @@ namespace clang {
|
||||
class SourceManager;
|
||||
class TargetInfo;
|
||||
// Decls
|
||||
class CXXMethodDecl;
|
||||
class CXXRecordDecl;
|
||||
class Decl;
|
||||
class FieldDecl;
|
||||
class ObjCIvarDecl;
|
||||
@ -57,6 +59,7 @@ namespace clang {
|
||||
class TypeDecl;
|
||||
class TypedefDecl;
|
||||
class UsingDecl;
|
||||
class UsingShadowDecl;
|
||||
|
||||
namespace Builtin { class Context; }
|
||||
|
||||
@ -105,6 +108,9 @@ class ASTContext {
|
||||
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
|
||||
llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts;
|
||||
|
||||
/// KeyFunctions - A cache mapping from CXXRecordDecls to key functions.
|
||||
llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions;
|
||||
|
||||
/// \brief Mapping from ObjCContainers to their ObjCImplementations.
|
||||
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
|
||||
|
||||
@ -183,8 +189,10 @@ class ASTContext {
|
||||
llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>
|
||||
InstantiatedFromStaticDataMember;
|
||||
|
||||
/// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls
|
||||
/// where created during instantiation.
|
||||
/// \brief Keeps track of the declaration from which a UsingDecl was
|
||||
/// created during instantiation. The source declaration is always
|
||||
/// a UsingDecl, an UnresolvedUsingValueDecl, or an
|
||||
/// UnresolvedUsingTypenameDecl.
|
||||
///
|
||||
/// For example:
|
||||
/// \code
|
||||
@ -203,8 +211,10 @@ class ASTContext {
|
||||
///
|
||||
/// This mapping will contain an entry that maps from the UsingDecl in
|
||||
/// B<int> to the UnresolvedUsingDecl in B<T>.
|
||||
llvm::DenseMap<UsingDecl *, NamedDecl *>
|
||||
InstantiatedFromUnresolvedUsingDecl;
|
||||
llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl;
|
||||
|
||||
llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>
|
||||
InstantiatedFromUsingShadowDecl;
|
||||
|
||||
llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
|
||||
|
||||
@ -282,14 +292,18 @@ class ASTContext {
|
||||
void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
|
||||
TemplateSpecializationKind TSK);
|
||||
|
||||
/// \brief If this using decl is instantiated from an unresolved using decl,
|
||||
/// \brief If the given using decl is an instantiation of a
|
||||
/// (possibly unresolved) using decl from a template instantiation,
|
||||
/// return it.
|
||||
NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
|
||||
NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst);
|
||||
|
||||
/// \brief Note that the using decl \p Inst is an instantiation of
|
||||
/// the unresolved using decl \p Tmpl of a class template.
|
||||
void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl);
|
||||
/// \brief Remember that the using decl \p Inst is an instantiation
|
||||
/// of the using decl \p Pattern of a class template.
|
||||
void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern);
|
||||
|
||||
void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
|
||||
UsingShadowDecl *Pattern);
|
||||
UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst);
|
||||
|
||||
FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);
|
||||
|
||||
@ -380,9 +394,10 @@ class ASTContext {
|
||||
/// equivalent to calling T.withConst().
|
||||
QualType getConstType(QualType T) { return T.withConst(); }
|
||||
|
||||
/// getNoReturnType - Add the noreturn attribute to the given type which must
|
||||
/// be a FunctionType or a pointer to an allowable type or a BlockPointer.
|
||||
QualType getNoReturnType(QualType T);
|
||||
/// getNoReturnType - Add or remove the noreturn attribute to the given type
|
||||
/// which must be a FunctionType or a pointer to an allowable type or a
|
||||
/// BlockPointer.
|
||||
QualType getNoReturnType(QualType T, bool AddNoReturn = true);
|
||||
|
||||
/// getComplexType - Return the uniqued reference to the type for a complex
|
||||
/// number with the specified element type.
|
||||
@ -569,7 +584,7 @@ class ASTContext {
|
||||
|
||||
/// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
|
||||
/// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
|
||||
QualType getSizeType() const;
|
||||
CanQualType getSizeType() const;
|
||||
|
||||
/// getWCharType - In C++, this returns the unique wchar_t type. In C99, this
|
||||
/// returns a type compatible with the type defined in <stddef.h> as defined
|
||||
@ -735,12 +750,12 @@ class ASTContext {
|
||||
|
||||
DeclarationName getNameForTemplate(TemplateName Name);
|
||||
|
||||
TemplateName getOverloadedTemplateName(NamedDecl * const *Begin,
|
||||
NamedDecl * const *End);
|
||||
|
||||
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
TemplateDecl *Template);
|
||||
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
OverloadedFunctionDecl *Template);
|
||||
|
||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name);
|
||||
@ -843,6 +858,13 @@ class ASTContext {
|
||||
const ASTRecordLayout &
|
||||
getASTObjCImplementationLayout(const ObjCImplementationDecl *D);
|
||||
|
||||
/// getKeyFunction - Get the key function for the given record decl.
|
||||
/// The key function is, according to the Itanium C++ ABI section 5.2.3:
|
||||
///
|
||||
/// ...the first non-pure virtual function that is not inline at the point
|
||||
/// of class definition.
|
||||
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
|
||||
|
||||
void CollectObjCIvars(const ObjCInterfaceDecl *OI,
|
||||
llvm::SmallVectorImpl<FieldDecl*> &Fields);
|
||||
|
||||
@ -1108,9 +1130,9 @@ class ASTContext {
|
||||
void setObjCImplementation(ObjCCategoryDecl *CatD,
|
||||
ObjCCategoryImplDecl *ImplD);
|
||||
|
||||
/// \brief Allocate an uninitialized DeclaratorInfo.
|
||||
/// \brief Allocate an uninitialized TypeSourceInfo.
|
||||
///
|
||||
/// The caller should initialize the memory held by DeclaratorInfo using
|
||||
/// The caller should initialize the memory held by TypeSourceInfo using
|
||||
/// the TypeLoc wrappers.
|
||||
///
|
||||
/// \param T the type that will be the basis for type source info. This type
|
||||
@ -1119,13 +1141,13 @@ class ASTContext {
|
||||
///
|
||||
/// \param Size the size of the type info to create, or 0 if the size
|
||||
/// should be calculated based on the type.
|
||||
DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0);
|
||||
TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0);
|
||||
|
||||
/// \brief Allocate a DeclaratorInfo where all locations have been
|
||||
/// \brief Allocate a TypeSourceInfo where all locations have been
|
||||
/// initialized to a given location, which defaults to the empty
|
||||
/// location.
|
||||
DeclaratorInfo *
|
||||
getTrivialDeclaratorInfo(QualType T, SourceLocation Loc = SourceLocation());
|
||||
TypeSourceInfo *
|
||||
getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation());
|
||||
|
||||
private:
|
||||
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
|
||||
|
@ -172,6 +172,12 @@ inline bool operator!=(CanQual<T> x, CanQual<U> y) {
|
||||
/// \brief Represents a canonical, potentially-qualified type.
|
||||
typedef CanQual<Type> CanQualType;
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
CanQualType T) {
|
||||
DB << static_cast<QualType>(T);
|
||||
return DB;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Internal proxy classes used by canonical types
|
||||
//----------------------------------------------------------------------------//
|
||||
|
@ -35,17 +35,17 @@ class TypeLoc;
|
||||
///
|
||||
/// A client can read the relevant info using TypeLoc wrappers, e.g:
|
||||
/// @code
|
||||
/// TypeLoc TL = DeclaratorInfo->getTypeLoc();
|
||||
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
|
||||
/// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL))
|
||||
/// PL->getStarLoc().print(OS, SrcMgr);
|
||||
/// @endcode
|
||||
///
|
||||
class DeclaratorInfo {
|
||||
class TypeSourceInfo {
|
||||
QualType Ty;
|
||||
// Contains a memory block after the class, used for type source information,
|
||||
// allocated by ASTContext.
|
||||
friend class ASTContext;
|
||||
DeclaratorInfo(QualType ty) : Ty(ty) { }
|
||||
TypeSourceInfo(QualType ty) : Ty(ty) { }
|
||||
public:
|
||||
/// \brief Return the type wrapped by this type source info.
|
||||
QualType getType() const { return Ty; }
|
||||
@ -322,18 +322,18 @@ class ValueDecl : public NamedDecl {
|
||||
};
|
||||
|
||||
/// \brief Represents a ValueDecl that came out of a declarator.
|
||||
/// Contains type source information through DeclaratorInfo.
|
||||
/// Contains type source information through TypeSourceInfo.
|
||||
class DeclaratorDecl : public ValueDecl {
|
||||
DeclaratorInfo *DeclInfo;
|
||||
TypeSourceInfo *DeclInfo;
|
||||
|
||||
protected:
|
||||
DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName N, QualType T, DeclaratorInfo *DInfo)
|
||||
: ValueDecl(DK, DC, L, N, T), DeclInfo(DInfo) {}
|
||||
DeclarationName N, QualType T, TypeSourceInfo *TInfo)
|
||||
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}
|
||||
|
||||
public:
|
||||
DeclaratorInfo *getDeclaratorInfo() const { return DeclInfo; }
|
||||
void setDeclaratorInfo(DeclaratorInfo *DInfo) { DeclInfo = DInfo; }
|
||||
TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
|
||||
void setTypeSourceInfo(TypeSourceInfo *TInfo) { DeclInfo = TInfo; }
|
||||
|
||||
SourceLocation getTypeSpecStartLoc() const;
|
||||
|
||||
@ -348,15 +348,23 @@ class DeclaratorDecl : public ValueDecl {
|
||||
/// which it was evaluated (if any), and whether or not the statement
|
||||
/// is an integral constant expression (if known).
|
||||
struct EvaluatedStmt {
|
||||
EvaluatedStmt() : WasEvaluated(false), CheckedICE(false), IsICE(false) { }
|
||||
EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
|
||||
CheckingICE(false), IsICE(false) { }
|
||||
|
||||
/// \brief Whether this statement was already evaluated.
|
||||
bool WasEvaluated : 1;
|
||||
|
||||
/// \brief Whether this statement is being evaluated.
|
||||
bool IsEvaluating : 1;
|
||||
|
||||
/// \brief Whether we already checked whether this statement was an
|
||||
/// integral constant expression.
|
||||
bool CheckedICE : 1;
|
||||
|
||||
/// \brief Whether we are checking whether this statement is an
|
||||
/// integral constant expression.
|
||||
bool CheckingICE : 1;
|
||||
|
||||
/// \brief Whether this statement is an integral constant
|
||||
/// expression. Only valid if CheckedICE is true.
|
||||
bool IsICE : 1;
|
||||
@ -432,8 +440,8 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
friend class StmtIteratorBase;
|
||||
protected:
|
||||
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo, StorageClass SC)
|
||||
: DeclaratorDecl(DK, DC, L, Id, T, DInfo), Init(),
|
||||
QualType T, TypeSourceInfo *TInfo, StorageClass SC)
|
||||
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
|
||||
ThreadSpecified(false), HasCXXDirectInit(false),
|
||||
DeclaredInCondition(false) {
|
||||
SClass = SC;
|
||||
@ -453,7 +461,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
|
||||
static VarDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo, StorageClass S);
|
||||
QualType T, TypeSourceInfo *TInfo, StorageClass S);
|
||||
|
||||
virtual ~VarDecl();
|
||||
virtual void Destroy(ASTContext& C);
|
||||
@ -504,23 +512,45 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
|
||||
void setInit(ASTContext &C, Expr *I);
|
||||
|
||||
/// \brief Note that constant evaluation has computed the given
|
||||
/// value for this variable's initializer.
|
||||
void setEvaluatedValue(ASTContext &C, const APValue &Value) const {
|
||||
EvaluatedStmt *EnsureEvaluatedStmt() const {
|
||||
EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
|
||||
if (!Eval) {
|
||||
Stmt *S = Init.get<Stmt *>();
|
||||
Eval = new (C) EvaluatedStmt;
|
||||
Eval = new (getASTContext()) EvaluatedStmt;
|
||||
Eval->Value = S;
|
||||
Init = Eval;
|
||||
}
|
||||
return Eval;
|
||||
}
|
||||
|
||||
/// \brief Check whether we are in the process of checking whether the
|
||||
/// initializer can be evaluated.
|
||||
bool isEvaluatingValue() const {
|
||||
if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
|
||||
return Eval->IsEvaluating;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Note that we now are checking whether the initializer can be
|
||||
/// evaluated.
|
||||
void setEvaluatingValue() const {
|
||||
EvaluatedStmt *Eval = EnsureEvaluatedStmt();
|
||||
Eval->IsEvaluating = true;
|
||||
}
|
||||
|
||||
/// \brief Note that constant evaluation has computed the given
|
||||
/// value for this variable's initializer.
|
||||
void setEvaluatedValue(const APValue &Value) const {
|
||||
EvaluatedStmt *Eval = EnsureEvaluatedStmt();
|
||||
Eval->IsEvaluating = false;
|
||||
Eval->WasEvaluated = true;
|
||||
Eval->Evaluated = Value;
|
||||
}
|
||||
|
||||
/// \brief Return the already-evaluated value of this variable's
|
||||
/// initializer, or NULL if the value is not yet known.
|
||||
/// initializer, or NULL if the value is not yet known. Returns pointer
|
||||
/// to untyped APValue if the value could not be evaluated.
|
||||
APValue *getEvaluatedValue() const {
|
||||
if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
|
||||
if (Eval->WasEvaluated)
|
||||
@ -548,17 +578,27 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
return Init.get<EvaluatedStmt *>()->IsICE;
|
||||
}
|
||||
|
||||
/// \brief Check whether we are in the process of checking the initializer
|
||||
/// is an integral constant expression.
|
||||
bool isCheckingICE() const {
|
||||
if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
|
||||
return Eval->CheckingICE;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Note that we now are checking whether the initializer is an
|
||||
/// integral constant expression.
|
||||
void setCheckingICE() const {
|
||||
EvaluatedStmt *Eval = EnsureEvaluatedStmt();
|
||||
Eval->CheckingICE = true;
|
||||
}
|
||||
|
||||
/// \brief Note that we now know whether the initializer is an
|
||||
/// integral constant expression.
|
||||
void setInitKnownICE(ASTContext &C, bool IsICE) const {
|
||||
EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
|
||||
if (!Eval) {
|
||||
Stmt *S = Init.get<Stmt *>();
|
||||
Eval = new (C) EvaluatedStmt;
|
||||
Eval->Value = S;
|
||||
Init = Eval;
|
||||
}
|
||||
|
||||
void setInitKnownICE(bool IsICE) const {
|
||||
EvaluatedStmt *Eval = EnsureEvaluatedStmt();
|
||||
Eval->CheckingICE = false;
|
||||
Eval->CheckedICE = true;
|
||||
Eval->IsICE = IsICE;
|
||||
}
|
||||
@ -712,7 +752,7 @@ class ImplicitParamDecl : public VarDecl {
|
||||
protected:
|
||||
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType Tw)
|
||||
: VarDecl(DK, DC, L, Id, Tw, /*DInfo=*/0, VarDecl::None) {}
|
||||
: VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None) {}
|
||||
public:
|
||||
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
@ -739,16 +779,16 @@ class ParmVarDecl : public VarDecl {
|
||||
|
||||
protected:
|
||||
ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo,
|
||||
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, Expr *DefArg)
|
||||
: VarDecl(DK, DC, L, Id, T, DInfo, S), objcDeclQualifier(OBJC_TQ_None) {
|
||||
: VarDecl(DK, DC, L, Id, T, TInfo, S), objcDeclQualifier(OBJC_TQ_None) {
|
||||
setDefaultArg(DefArg);
|
||||
}
|
||||
|
||||
public:
|
||||
static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, Expr *DefArg);
|
||||
|
||||
ObjCDeclQualifier getObjCDeclQualifier() const {
|
||||
@ -822,8 +862,8 @@ class ParmVarDecl : public VarDecl {
|
||||
}
|
||||
|
||||
QualType getOriginalType() const {
|
||||
if (getDeclaratorInfo())
|
||||
return getDeclaratorInfo()->getType();
|
||||
if (getTypeSourceInfo())
|
||||
return getTypeSourceInfo()->getType();
|
||||
return getType();
|
||||
}
|
||||
|
||||
@ -907,9 +947,9 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
|
||||
protected:
|
||||
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName N, QualType T, DeclaratorInfo *DInfo,
|
||||
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, bool isInline)
|
||||
: DeclaratorDecl(DK, DC, L, N, T, DInfo),
|
||||
: DeclaratorDecl(DK, DC, L, N, T, TInfo),
|
||||
DeclContext(DK),
|
||||
ParamInfo(0), Body(),
|
||||
SClass(S), IsInline(isInline),
|
||||
@ -936,7 +976,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
|
||||
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName N, QualType T,
|
||||
DeclaratorInfo *DInfo,
|
||||
TypeSourceInfo *TInfo,
|
||||
StorageClass S = None, bool isInline = false,
|
||||
bool hasWrittenPrototype = true);
|
||||
|
||||
@ -1272,15 +1312,15 @@ class FieldDecl : public DeclaratorDecl {
|
||||
Expr *BitWidth;
|
||||
protected:
|
||||
FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo,
|
||||
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
|
||||
Expr *BW, bool Mutable)
|
||||
: DeclaratorDecl(DK, DC, L, Id, T, DInfo), Mutable(Mutable), BitWidth(BW) {
|
||||
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Mutable(Mutable), BitWidth(BW) {
|
||||
}
|
||||
|
||||
public:
|
||||
static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
DeclaratorInfo *DInfo, Expr *BW, bool Mutable);
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable);
|
||||
|
||||
/// isMutable - Determines whether this field is mutable (C++ only).
|
||||
bool isMutable() const { return Mutable; }
|
||||
@ -1383,28 +1423,28 @@ class TypeDecl : public NamedDecl {
|
||||
|
||||
class TypedefDecl : public TypeDecl {
|
||||
/// UnderlyingType - This is the type the typedef is set to.
|
||||
DeclaratorInfo *DInfo;
|
||||
TypeSourceInfo *TInfo;
|
||||
|
||||
TypedefDecl(DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, DeclaratorInfo *DInfo)
|
||||
: TypeDecl(Typedef, DC, L, Id), DInfo(DInfo) {}
|
||||
IdentifierInfo *Id, TypeSourceInfo *TInfo)
|
||||
: TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
|
||||
|
||||
virtual ~TypedefDecl() {}
|
||||
public:
|
||||
|
||||
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
DeclaratorInfo *DInfo);
|
||||
TypeSourceInfo *TInfo);
|
||||
|
||||
DeclaratorInfo *getTypeDeclaratorInfo() const {
|
||||
return DInfo;
|
||||
TypeSourceInfo *getTypeSourceInfo() const {
|
||||
return TInfo;
|
||||
}
|
||||
|
||||
QualType getUnderlyingType() const {
|
||||
return DInfo->getType();
|
||||
return TInfo->getType();
|
||||
}
|
||||
void setTypeDeclaratorInfo(DeclaratorInfo *newType) {
|
||||
DInfo = newType;
|
||||
void setTypeSourceInfo(TypeSourceInfo *newType) {
|
||||
TInfo = newType;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
@ -1554,6 +1594,12 @@ class EnumDecl : public TagDecl {
|
||||
/// have a different type than this does.
|
||||
QualType IntegerType;
|
||||
|
||||
/// PromotionType - The integer type that values of this type should
|
||||
/// promote to. In C, enumerators are generally of an integer type
|
||||
/// directly, but gcc-style large enumerators (and all enumerators
|
||||
/// in C++) are of the enum type instead.
|
||||
QualType PromotionType;
|
||||
|
||||
/// \brief If the enumeration was instantiated from an enumeration
|
||||
/// within a class or function template, this pointer refers to the
|
||||
/// enumeration declared within the template.
|
||||
@ -1583,7 +1629,8 @@ class EnumDecl : public TagDecl {
|
||||
/// declaration as being defined; it's enumerators have already been
|
||||
/// added (via DeclContext::addDecl). NewType is the new underlying
|
||||
/// type of the enumeration type.
|
||||
void completeDefinition(ASTContext &C, QualType NewType);
|
||||
void completeDefinition(ASTContext &C, QualType NewType,
|
||||
QualType PromotionType);
|
||||
|
||||
// enumerator_iterator - Iterates through the enumerators of this
|
||||
// enumeration.
|
||||
@ -1597,6 +1644,13 @@ class EnumDecl : public TagDecl {
|
||||
return enumerator_iterator(this->decls_end());
|
||||
}
|
||||
|
||||
/// getPromotionType - Return the integer type that enumerators
|
||||
/// should promote to.
|
||||
QualType getPromotionType() const { return PromotionType; }
|
||||
|
||||
/// \brief Set the promotion type.
|
||||
void setPromotionType(QualType T) { PromotionType = T; }
|
||||
|
||||
/// getIntegerType - Return the integer type this enum decl corresponds to.
|
||||
/// This returns a null qualtype for an enum forward definition.
|
||||
QualType getIntegerType() const { return IntegerType; }
|
||||
|
@ -91,7 +91,7 @@ class Decl {
|
||||
IDNS_Ordinary = 0x8,
|
||||
IDNS_ObjCProtocol = 0x10,
|
||||
IDNS_ObjCImplementation = 0x20,
|
||||
IDNS_ObjCCategoryImpl = 0x40,
|
||||
IDNS_ObjCCategoryName = 0x40,
|
||||
IDNS_OrdinaryFriend = 0x80,
|
||||
IDNS_TagFriend = 0x100,
|
||||
IDNS_Using = 0x200
|
||||
@ -916,6 +916,9 @@ class DeclContext {
|
||||
/// only happens with friends.
|
||||
void addHiddenDecl(Decl *D);
|
||||
|
||||
/// @brief Removes a declaration from this context.
|
||||
void removeDecl(Decl *D);
|
||||
|
||||
/// lookup_iterator - An iterator that provides access to the results
|
||||
/// of looking up a name within this context.
|
||||
typedef NamedDecl **lookup_iterator;
|
||||
@ -1003,6 +1006,8 @@ class DeclContext {
|
||||
static bool classof(const Name##Decl *D) { return true; }
|
||||
#include "clang/AST/DeclNodes.def"
|
||||
|
||||
void dumpDeclContext() const;
|
||||
|
||||
private:
|
||||
void LoadLexicalDeclsFromExternalStorage() const;
|
||||
void LoadVisibleDeclsFromExternalStorage() const;
|
||||
|
@ -88,108 +88,6 @@ namespace llvm {
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// OverloadedFunctionDecl - An instance of this class represents a
|
||||
/// set of overloaded functions. All of the functions have the same
|
||||
/// name and occur within the same scope.
|
||||
///
|
||||
/// An OverloadedFunctionDecl has no ownership over the FunctionDecl
|
||||
/// nodes it contains. Rather, the FunctionDecls are owned by the
|
||||
/// enclosing scope (which also owns the OverloadedFunctionDecl
|
||||
/// node). OverloadedFunctionDecl is used primarily to store a set of
|
||||
/// overloaded functions for name lookup.
|
||||
class OverloadedFunctionDecl : public NamedDecl {
|
||||
protected:
|
||||
OverloadedFunctionDecl(DeclContext *DC, DeclarationName N)
|
||||
: NamedDecl(OverloadedFunction, DC, SourceLocation(), N) { }
|
||||
|
||||
/// Functions - the set of overloaded functions contained in this
|
||||
/// overload set.
|
||||
llvm::SmallVector<AnyFunctionDecl, 4> Functions;
|
||||
|
||||
// FIXME: This should go away when we stop using
|
||||
// OverloadedFunctionDecl to store conversions in CXXRecordDecl.
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
public:
|
||||
typedef llvm::SmallVector<AnyFunctionDecl, 4>::iterator function_iterator;
|
||||
typedef llvm::SmallVector<AnyFunctionDecl, 4>::const_iterator
|
||||
function_const_iterator;
|
||||
|
||||
static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
DeclarationName N);
|
||||
|
||||
/// \brief Add a new overloaded function or function template to the set
|
||||
/// of overloaded function templates.
|
||||
void addOverload(AnyFunctionDecl F);
|
||||
|
||||
function_iterator function_begin() { return Functions.begin(); }
|
||||
function_iterator function_end() { return Functions.end(); }
|
||||
function_const_iterator function_begin() const { return Functions.begin(); }
|
||||
function_const_iterator function_end() const { return Functions.end(); }
|
||||
|
||||
/// \brief Returns the number of overloaded functions stored in
|
||||
/// this set.
|
||||
unsigned size() const { return Functions.size(); }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == OverloadedFunction;
|
||||
}
|
||||
static bool classof(const OverloadedFunctionDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Provides uniform iteration syntax for an overload set, function,
|
||||
/// or function template.
|
||||
class OverloadIterator {
|
||||
/// \brief An overloaded function set, function declaration, or
|
||||
/// function template declaration.
|
||||
NamedDecl *D;
|
||||
|
||||
/// \brief If the declaration is an overloaded function set, this is the
|
||||
/// iterator pointing to the current position within that overloaded
|
||||
/// function set.
|
||||
OverloadedFunctionDecl::function_iterator Iter;
|
||||
|
||||
public:
|
||||
typedef AnyFunctionDecl value_type;
|
||||
typedef value_type reference;
|
||||
typedef NamedDecl *pointer;
|
||||
typedef int difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
OverloadIterator() : D(0) { }
|
||||
|
||||
OverloadIterator(FunctionDecl *FD) : D(FD) { }
|
||||
OverloadIterator(FunctionTemplateDecl *FTD)
|
||||
: D(reinterpret_cast<NamedDecl*>(FTD)) { }
|
||||
OverloadIterator(OverloadedFunctionDecl *Ovl)
|
||||
: D(Ovl), Iter(Ovl->function_begin()) { }
|
||||
|
||||
OverloadIterator(NamedDecl *ND);
|
||||
|
||||
reference operator*() const;
|
||||
|
||||
pointer operator->() const { return (**this).get(); }
|
||||
|
||||
OverloadIterator &operator++();
|
||||
|
||||
OverloadIterator operator++(int) {
|
||||
OverloadIterator Temp(*this);
|
||||
++(*this);
|
||||
return Temp;
|
||||
}
|
||||
|
||||
bool Equals(const OverloadIterator &Other) const;
|
||||
};
|
||||
|
||||
inline bool operator==(const OverloadIterator &X, const OverloadIterator &Y) {
|
||||
return X.Equals(Y);
|
||||
}
|
||||
|
||||
inline bool operator!=(const OverloadIterator &X, const OverloadIterator &Y) {
|
||||
return !(X == Y);
|
||||
}
|
||||
|
||||
/// CXXBaseSpecifier - A base class of a C++ class.
|
||||
///
|
||||
/// Each CXXBaseSpecifier represents a single, direct base class (or
|
||||
@ -210,6 +108,7 @@ class CXXBaseSpecifier {
|
||||
/// Range - The source code range that covers the full base
|
||||
/// specifier, including the "virtual" (if present) and access
|
||||
/// specifier (if present).
|
||||
// FIXME: Move over to a TypeLoc!
|
||||
SourceRange Range;
|
||||
|
||||
/// Virtual - Whether this is a virtual base class or not.
|
||||
@ -635,6 +534,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// [dcl.init.aggr]).
|
||||
void setAggregate(bool Agg) { Aggregate = Agg; }
|
||||
|
||||
/// setMethodAsVirtual - Make input method virtual and set the necesssary
|
||||
/// special function bits and other bits accordingly.
|
||||
void setMethodAsVirtual(FunctionDecl *Method);
|
||||
|
||||
/// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
|
||||
/// that is an aggregate that has no non-static non-POD data members, no
|
||||
/// reference data members, no user-defined copy assignment operator and no
|
||||
@ -753,7 +656,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief Determine whether this particular class is a specialization or
|
||||
/// instantiation of a class template or member class of a class template,
|
||||
/// and how it was instantiated or specialized.
|
||||
TemplateSpecializationKind getTemplateSpecializationKind();
|
||||
TemplateSpecializationKind getTemplateSpecializationKind() const;
|
||||
|
||||
/// \brief Set the kind of specialization or template instantiation this is.
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
|
||||
@ -762,7 +665,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
|
||||
|
||||
/// getDestructor - Returns the destructor decl for this class.
|
||||
const CXXDestructorDecl *getDestructor(ASTContext &Context);
|
||||
CXXDestructorDecl *getDestructor(ASTContext &Context);
|
||||
|
||||
/// isLocalClass - If the class is a local class [class.local], returns
|
||||
/// the enclosing function declaration.
|
||||
@ -802,6 +705,30 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
|
||||
/// tangling input and output in \p Paths
|
||||
bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
|
||||
|
||||
/// \brief Determine whether this class is provably not derived from
|
||||
/// the type \p Base.
|
||||
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const;
|
||||
|
||||
/// \brief Function type used by forallBases() as a callback.
|
||||
///
|
||||
/// \param Base the definition of the base class
|
||||
///
|
||||
/// \returns true if this base matched the search criteria
|
||||
typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
|
||||
void *UserData);
|
||||
|
||||
/// \brief Determines if the given callback holds for all the direct
|
||||
/// or indirect base classes of this type.
|
||||
///
|
||||
/// The class itself does not count as a base class. This routine
|
||||
/// returns false if the class has non-computable base classes.
|
||||
///
|
||||
/// \param AllowShortCircuit if false, forces the callback to be called
|
||||
/// for every base class, even if a dependent or non-matching base was
|
||||
/// found.
|
||||
bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
|
||||
bool AllowShortCircuit = true) const;
|
||||
|
||||
/// \brief Function type used by lookupInBases() to determine whether a
|
||||
/// specific base class subobject matches the lookup criteria.
|
||||
@ -902,15 +829,15 @@ class CXXRecordDecl : public RecordDecl {
|
||||
class CXXMethodDecl : public FunctionDecl {
|
||||
protected:
|
||||
CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T, DeclaratorInfo *DInfo,
|
||||
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isStatic, bool isInline)
|
||||
: FunctionDecl(DK, RD, L, N, T, DInfo, (isStatic ? Static : None),
|
||||
: FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None),
|
||||
isInline) {}
|
||||
|
||||
public:
|
||||
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isStatic = false,
|
||||
bool isInline = false);
|
||||
|
||||
@ -968,6 +895,8 @@ class CXXMethodDecl : public FunctionDecl {
|
||||
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
|
||||
}
|
||||
|
||||
bool hasInlineBody() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion;
|
||||
@ -990,12 +919,13 @@ class CXXMethodDecl : public FunctionDecl {
|
||||
/// };
|
||||
/// @endcode
|
||||
class CXXBaseOrMemberInitializer {
|
||||
/// BaseOrMember - This points to the entity being initialized,
|
||||
/// which is either a base class (a Type) or a non-static data
|
||||
/// member. When the low bit is 1, it's a base
|
||||
/// class; when the low bit is 0, it's a member.
|
||||
uintptr_t BaseOrMember;
|
||||
|
||||
/// \brief Either the base class name (stored as a TypeSourceInfo*) or the
|
||||
/// field being initialized.
|
||||
llvm::PointerUnion<TypeSourceInfo *, FieldDecl *> BaseOrMember;
|
||||
|
||||
/// \brief The source location for the field name.
|
||||
SourceLocation MemberLocation;
|
||||
|
||||
/// Args - The arguments used to initialize the base or member.
|
||||
Stmt **Args;
|
||||
unsigned NumArgs;
|
||||
@ -1020,8 +950,8 @@ class CXXBaseOrMemberInitializer {
|
||||
/// and AnonUnionMember holds field decl for au_i1.
|
||||
llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion;
|
||||
|
||||
/// IdLoc - Location of the id in ctor-initializer list.
|
||||
SourceLocation IdLoc;
|
||||
/// LParenLoc - Location of the left paren of the ctor-initializer.
|
||||
SourceLocation LParenLoc;
|
||||
|
||||
/// RParenLoc - Location of the right paren of the ctor-initializer.
|
||||
SourceLocation RParenLoc;
|
||||
@ -1029,18 +959,22 @@ class CXXBaseOrMemberInitializer {
|
||||
public:
|
||||
/// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
|
||||
explicit
|
||||
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs,
|
||||
CXXConstructorDecl *C,
|
||||
SourceLocation L, SourceLocation R);
|
||||
CXXBaseOrMemberInitializer(ASTContext &Context,
|
||||
TypeSourceInfo *TInfo, CXXConstructorDecl *C,
|
||||
SourceLocation L,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
SourceLocation R);
|
||||
|
||||
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
|
||||
explicit
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs,
|
||||
CXXConstructorDecl *C,
|
||||
SourceLocation L, SourceLocation R);
|
||||
CXXBaseOrMemberInitializer(ASTContext &Context,
|
||||
FieldDecl *Member, SourceLocation MemberLoc,
|
||||
CXXConstructorDecl *C, SourceLocation L,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
SourceLocation R);
|
||||
|
||||
/// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
|
||||
~CXXBaseOrMemberInitializer();
|
||||
/// \brief Destroy the base or member initializer.
|
||||
void Destroy(ASTContext &Context);
|
||||
|
||||
/// arg_iterator - Iterates through the member initialization
|
||||
/// arguments.
|
||||
@ -1050,54 +984,54 @@ class CXXBaseOrMemberInitializer {
|
||||
/// arguments.
|
||||
typedef ConstExprIterator const_arg_iterator;
|
||||
|
||||
/// getBaseOrMember - get the generic 'member' representing either the field
|
||||
/// or a base class.
|
||||
void* getBaseOrMember() const { return reinterpret_cast<void*>(BaseOrMember); }
|
||||
|
||||
/// isBaseInitializer - Returns true when this initializer is
|
||||
/// initializing a base class.
|
||||
bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; }
|
||||
bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
|
||||
|
||||
/// isMemberInitializer - Returns true when this initializer is
|
||||
/// initializing a non-static data member.
|
||||
bool isMemberInitializer() const { return (BaseOrMember & 0x1) == 0; }
|
||||
bool isMemberInitializer() const { return BaseOrMember.is<FieldDecl*>(); }
|
||||
|
||||
/// getBaseClass - If this is a base class initializer, returns the
|
||||
/// type used to specify the initializer. The resulting type will be
|
||||
/// a class type or a typedef of a class type. If this is not a base
|
||||
/// class initializer, returns NULL.
|
||||
Type *getBaseClass() {
|
||||
if (isBaseInitializer())
|
||||
return reinterpret_cast<Type*>(BaseOrMember & ~0x01);
|
||||
else
|
||||
return 0;
|
||||
/// If this is a base class initializer, returns the type of the
|
||||
/// base class with location information. Otherwise, returns an NULL
|
||||
/// type location.
|
||||
TypeLoc getBaseClassLoc() const;
|
||||
|
||||
/// If this is a base class initializer, returns the type of the base class.
|
||||
/// Otherwise, returns NULL.
|
||||
const Type *getBaseClass() const;
|
||||
Type *getBaseClass();
|
||||
|
||||
/// \brief Returns the declarator information for a base class initializer.
|
||||
TypeSourceInfo *getBaseClassInfo() const {
|
||||
return BaseOrMember.dyn_cast<TypeSourceInfo *>();
|
||||
}
|
||||
|
||||
/// getBaseClass - If this is a base class initializer, returns the
|
||||
/// type used to specify the initializer. The resulting type will be
|
||||
/// a class type or a typedef of a class type. If this is not a base
|
||||
/// class initializer, returns NULL.
|
||||
const Type *getBaseClass() const {
|
||||
if (isBaseInitializer())
|
||||
return reinterpret_cast<const Type*>(BaseOrMember & ~0x01);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// getMember - If this is a member initializer, returns the
|
||||
/// declaration of the non-static data member being
|
||||
/// initialized. Otherwise, returns NULL.
|
||||
FieldDecl *getMember() {
|
||||
if (isMemberInitializer())
|
||||
return reinterpret_cast<FieldDecl *>(BaseOrMember);
|
||||
return BaseOrMember.get<FieldDecl*>();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setMember(FieldDecl * anonUnionField) {
|
||||
BaseOrMember = reinterpret_cast<uintptr_t>(anonUnionField);
|
||||
SourceLocation getMemberLocation() const {
|
||||
return MemberLocation;
|
||||
}
|
||||
|
||||
void setMember(FieldDecl *Member) {
|
||||
assert(isMemberInitializer());
|
||||
BaseOrMember = Member;
|
||||
}
|
||||
|
||||
/// \brief Determine the source location of the initializer.
|
||||
SourceLocation getSourceLocation() const;
|
||||
|
||||
/// \brief Determine the source range covering the entire initializer.
|
||||
SourceRange getSourceRange() const;
|
||||
|
||||
FieldDecl *getAnonUnionMember() const {
|
||||
return CtorOrAnonUnion.dyn_cast<FieldDecl *>();
|
||||
}
|
||||
@ -1109,7 +1043,7 @@ class CXXBaseOrMemberInitializer {
|
||||
return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>();
|
||||
}
|
||||
|
||||
SourceLocation getSourceLocation() const { return IdLoc; }
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||
|
||||
/// arg_begin() - Retrieve an iterator to the first initializer argument.
|
||||
@ -1155,9 +1089,9 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
unsigned NumBaseOrMemberInitializers;
|
||||
|
||||
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T, DeclaratorInfo *DInfo,
|
||||
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXConstructor, RD, L, N, T, DInfo, false, isInline),
|
||||
: CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, isInline),
|
||||
Explicit(isExplicit), ImplicitlyDefined(false),
|
||||
BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
@ -1167,7 +1101,7 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
public:
|
||||
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isExplicit,
|
||||
bool isInline, bool isImplicitlyDeclared);
|
||||
|
||||
@ -1294,7 +1228,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
||||
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T,
|
||||
bool isInline, bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline),
|
||||
: CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, isInline),
|
||||
ImplicitlyDefined(false), OperatorDelete(0) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
@ -1349,15 +1283,15 @@ class CXXConversionDecl : public CXXMethodDecl {
|
||||
bool Explicit : 1;
|
||||
|
||||
CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T, DeclaratorInfo *DInfo,
|
||||
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isExplicit)
|
||||
: CXXMethodDecl(CXXConversion, RD, L, N, T, DInfo, false, isInline),
|
||||
: CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, isInline),
|
||||
Explicit(isExplicit) { }
|
||||
|
||||
public:
|
||||
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isExplicit);
|
||||
|
||||
/// isExplicit - Whether this is an explicit conversion operator
|
||||
|
@ -131,6 +131,25 @@ struct StoredDeclsList {
|
||||
return DK == DK_DeclID || DK == DK_ID_Vector;
|
||||
}
|
||||
|
||||
void remove(NamedDecl *D) {
|
||||
assert(!isNull() && "removing from empty list");
|
||||
if (NamedDecl *Singleton = getAsDecl()) {
|
||||
assert(Singleton == D && "list is different singleton");
|
||||
(void)Singleton;
|
||||
Data = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
VectorTy &Vec = *getAsVector();
|
||||
VectorTy::iterator I = std::find(Vec.begin(), Vec.end(),
|
||||
reinterpret_cast<uintptr_t>(D));
|
||||
assert(I != Vec.end() && "list does not contain decl");
|
||||
Vec.erase(I);
|
||||
|
||||
assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D))
|
||||
== Vec.end() && "list still contains decl");
|
||||
}
|
||||
|
||||
/// getLookupResult - Return an array of all the decls that this list
|
||||
/// represents.
|
||||
DeclContext::lookup_result getLookupResult(ASTContext &Context) {
|
||||
@ -200,11 +219,37 @@ struct StoredDeclsList {
|
||||
}
|
||||
|
||||
VectorTy &Vec = *getAsVector();
|
||||
if (isa<UsingDirectiveDecl>(D) ||
|
||||
D->getIdentifierNamespace() == Decl::IDNS_Tag)
|
||||
|
||||
// Using directives end up in a special entry which contains only
|
||||
// other using directives, so all this logic is wasted for them.
|
||||
// But avoiding the logic wastes time in the far-more-common case
|
||||
// that we're *not* adding a new using directive.
|
||||
|
||||
// Tag declarations always go at the end of the list so that an
|
||||
// iterator which points at the first tag will start a span of
|
||||
// decls that only contains tags.
|
||||
if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
|
||||
Vec.push_back(reinterpret_cast<uintptr_t>(D));
|
||||
else if (reinterpret_cast<NamedDecl *>(Vec.back())
|
||||
->getIdentifierNamespace() == Decl::IDNS_Tag) {
|
||||
|
||||
// Resolved using declarations go at the front of the list so that
|
||||
// they won't show up in other lookup results. Unresolved using
|
||||
// declarations (which are always in IDNS_Using | IDNS_Ordinary)
|
||||
// follow that so that the using declarations will be contiguous.
|
||||
else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
|
||||
VectorTy::iterator I = Vec.begin();
|
||||
if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
|
||||
while (I != Vec.end() &&
|
||||
reinterpret_cast<NamedDecl *>(*I)
|
||||
->getIdentifierNamespace() == Decl::IDNS_Using)
|
||||
++I;
|
||||
}
|
||||
Vec.insert(I, reinterpret_cast<uintptr_t>(D));
|
||||
|
||||
// All other declarations go at the end of the list, but before any
|
||||
// tag declarations. But we can be clever about tag declarations
|
||||
// because there can only ever be one in a scope.
|
||||
} else if (reinterpret_cast<NamedDecl *>(Vec.back())
|
||||
->getIdentifierNamespace() == Decl::IDNS_Tag) {
|
||||
uintptr_t TagD = Vec.back();
|
||||
Vec.back() = reinterpret_cast<uintptr_t>(D);
|
||||
Vec.push_back(TagD);
|
||||
|
@ -75,7 +75,6 @@
|
||||
|
||||
DECL(TranslationUnit, Decl)
|
||||
ABSTRACT_DECL(Named, Decl)
|
||||
DECL(OverloadedFunction, NamedDecl)
|
||||
DECL(Namespace, NamedDecl)
|
||||
DECL(UsingDirective, NamedDecl)
|
||||
DECL(NamespaceAlias, NamedDecl)
|
||||
@ -143,7 +142,7 @@ DECL_CONTEXT_BASE(ObjCContainer)
|
||||
LAST_DECL_CONTEXT(Block)
|
||||
|
||||
// Declaration ranges
|
||||
DECL_RANGE(Named, OverloadedFunction, ObjCCompatibleAlias)
|
||||
DECL_RANGE(Named, Namespace, ObjCCompatibleAlias)
|
||||
DECL_RANGE(ObjCContainer, ObjCContainer, ObjCImplementation)
|
||||
DECL_RANGE(Field, Field, ObjCAtDefsField)
|
||||
DECL_RANGE(Type, Typedef, TemplateTypeParm)
|
||||
|
@ -578,14 +578,14 @@ class ObjCIvarDecl : public FieldDecl {
|
||||
|
||||
private:
|
||||
ObjCIvarDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo, AccessControl ac, Expr *BW)
|
||||
: FieldDecl(ObjCIvar, DC, L, Id, T, DInfo, BW, /*Mutable=*/false),
|
||||
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW)
|
||||
: FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false),
|
||||
DeclAccess(ac) {}
|
||||
|
||||
public:
|
||||
static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
DeclaratorInfo *DInfo,
|
||||
TypeSourceInfo *TInfo,
|
||||
AccessControl ac, Expr *BW = NULL);
|
||||
|
||||
void setAccessControl(AccessControl ac) { DeclAccess = ac; }
|
||||
@ -612,7 +612,7 @@ class ObjCAtDefsFieldDecl : public FieldDecl {
|
||||
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, Expr *BW)
|
||||
: FieldDecl(ObjCAtDefsField, DC, L, Id, T,
|
||||
/*DInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
|
||||
/*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
|
||||
BW, /*Mutable=*/false) {}
|
||||
|
||||
public:
|
||||
|
@ -573,7 +573,7 @@ class TemplateTypeParmDecl : public TypeDecl {
|
||||
bool ParameterPack : 1;
|
||||
|
||||
/// \brief The default template argument, if any.
|
||||
DeclaratorInfo *DefaultArgument;
|
||||
TypeSourceInfo *DefaultArgument;
|
||||
|
||||
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
bool Typename, QualType Type, bool ParameterPack)
|
||||
@ -601,7 +601,7 @@ class TemplateTypeParmDecl : public TypeDecl {
|
||||
QualType getDefaultArgument() const { return DefaultArgument->getType(); }
|
||||
|
||||
/// \brief Retrieves the default argument's source information, if any.
|
||||
DeclaratorInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
|
||||
TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
|
||||
|
||||
/// \brief Retrieves the location of the default argument declaration.
|
||||
SourceLocation getDefaultArgumentLoc() const;
|
||||
@ -613,7 +613,7 @@ class TemplateTypeParmDecl : public TypeDecl {
|
||||
/// \brief Set the default argument for this template parameter, and
|
||||
/// whether that default argument was inherited from another
|
||||
/// declaration.
|
||||
void setDefaultArgument(DeclaratorInfo *DefArg, bool Inherited) {
|
||||
void setDefaultArgument(TypeSourceInfo *DefArg, bool Inherited) {
|
||||
DefaultArgument = DefArg;
|
||||
InheritedDefault = Inherited;
|
||||
}
|
||||
@ -652,15 +652,15 @@ class NonTypeTemplateParmDecl
|
||||
|
||||
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
|
||||
unsigned P, IdentifierInfo *Id, QualType T,
|
||||
DeclaratorInfo *DInfo)
|
||||
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, DInfo, VarDecl::None),
|
||||
TypeSourceInfo *TInfo)
|
||||
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None),
|
||||
TemplateParmPosition(D, P), DefaultArgument(0)
|
||||
{ }
|
||||
|
||||
public:
|
||||
static NonTypeTemplateParmDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
|
||||
unsigned P, IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo);
|
||||
unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo);
|
||||
|
||||
using TemplateParmPosition::getDepth;
|
||||
using TemplateParmPosition::getPosition;
|
||||
|
@ -387,10 +387,11 @@ struct DenseMapInfo<clang::DeclarationName> {
|
||||
isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
|
||||
static inline bool isPod() { return true; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::DeclarationName> { static const bool value = true; };
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -309,6 +309,15 @@ class Expr : public Stmt {
|
||||
/// ParenExpr or CastExprs, returning their operand.
|
||||
Expr *IgnoreParenNoopCasts(ASTContext &Ctx);
|
||||
|
||||
/// \brief Determine whether this expression is a default function argument.
|
||||
///
|
||||
/// Default arguments are implicitly generated in the abstract syntax tree
|
||||
/// by semantic analysis for function calls, object constructions, etc. in
|
||||
/// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes;
|
||||
/// this routine also looks through any implicit casts to determine whether
|
||||
/// the expression is a default argument.
|
||||
bool isDefaultArgument() const;
|
||||
|
||||
const Expr* IgnoreParens() const {
|
||||
return const_cast<Expr*>(this)->IgnoreParens();
|
||||
}
|
||||
@ -389,7 +398,7 @@ class DeclRefExpr : public Expr {
|
||||
// indicate whether (1) the declaration's name was explicitly qualified and
|
||||
// (2) the declaration's name was followed by an explicit template
|
||||
// argument list.
|
||||
llvm::PointerIntPair<NamedDecl *, 2> DecoratedD;
|
||||
llvm::PointerIntPair<ValueDecl *, 2> DecoratedD;
|
||||
|
||||
// Loc - The location of the declaration name itself.
|
||||
SourceLocation Loc;
|
||||
@ -427,7 +436,7 @@ class DeclRefExpr : public Expr {
|
||||
}
|
||||
|
||||
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
|
||||
NamedDecl *D, SourceLocation NameLoc,
|
||||
ValueDecl *D, SourceLocation NameLoc,
|
||||
const TemplateArgumentListInfo *TemplateArgs,
|
||||
QualType T);
|
||||
|
||||
@ -436,13 +445,13 @@ class DeclRefExpr : public Expr {
|
||||
/// declaration reference expression.
|
||||
void computeDependence();
|
||||
|
||||
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
|
||||
DeclRefExpr(StmtClass SC, ValueDecl *d, QualType t, SourceLocation l) :
|
||||
Expr(SC, t, false, false), DecoratedD(d, 0), Loc(l) {
|
||||
computeDependence();
|
||||
}
|
||||
|
||||
public:
|
||||
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
|
||||
DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) :
|
||||
Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) {
|
||||
computeDependence();
|
||||
}
|
||||
@ -454,14 +463,14 @@ class DeclRefExpr : public Expr {
|
||||
static DeclRefExpr *Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D,
|
||||
ValueDecl *D,
|
||||
SourceLocation NameLoc,
|
||||
QualType T,
|
||||
const TemplateArgumentListInfo *TemplateArgs = 0);
|
||||
|
||||
NamedDecl *getDecl() { return DecoratedD.getPointer(); }
|
||||
const NamedDecl *getDecl() const { return DecoratedD.getPointer(); }
|
||||
void setDecl(NamedDecl *NewD) { DecoratedD.setPointer(NewD); }
|
||||
ValueDecl *getDecl() { return DecoratedD.getPointer(); }
|
||||
const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }
|
||||
void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); }
|
||||
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
@ -686,11 +695,6 @@ class FloatingLiteral : public Expr {
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
||||
// FIXME: The logic for computing the value of a predefined expr should go
|
||||
// into a method here that takes the inner-most code decl (a block, function
|
||||
// or objc method) that the expr lives in. This would allow sema and codegen
|
||||
// to be consistent for things like sizeof(__func__) etc.
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
@ -975,7 +979,7 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
bool isSizeof : 1; // true if sizeof, false if alignof.
|
||||
bool isType : 1; // true if operand is a type, false if an expression
|
||||
union {
|
||||
DeclaratorInfo *Ty;
|
||||
TypeSourceInfo *Ty;
|
||||
Stmt *Ex;
|
||||
} Argument;
|
||||
SourceLocation OpLoc, RParenLoc;
|
||||
@ -984,15 +988,15 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
virtual void DoDestroy(ASTContext& C);
|
||||
|
||||
public:
|
||||
SizeOfAlignOfExpr(bool issizeof, DeclaratorInfo *DInfo,
|
||||
SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
|
||||
QualType resultType, SourceLocation op,
|
||||
SourceLocation rp) :
|
||||
Expr(SizeOfAlignOfExprClass, resultType,
|
||||
false, // Never type-dependent (C++ [temp.dep.expr]p3).
|
||||
// Value-dependent if the argument is type-dependent.
|
||||
DInfo->getType()->isDependentType()),
|
||||
TInfo->getType()->isDependentType()),
|
||||
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
|
||||
Argument.Ty = DInfo;
|
||||
Argument.Ty = TInfo;
|
||||
}
|
||||
|
||||
SizeOfAlignOfExpr(bool issizeof, Expr *E,
|
||||
@ -1017,7 +1021,7 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
QualType getArgumentType() const {
|
||||
return getArgumentTypeInfo()->getType();
|
||||
}
|
||||
DeclaratorInfo *getArgumentTypeInfo() const {
|
||||
TypeSourceInfo *getArgumentTypeInfo() const {
|
||||
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
|
||||
return Argument.Ty;
|
||||
}
|
||||
@ -1030,8 +1034,8 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
}
|
||||
|
||||
void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
|
||||
void setArgument(DeclaratorInfo *DInfo) {
|
||||
Argument.Ty = DInfo;
|
||||
void setArgument(TypeSourceInfo *TInfo) {
|
||||
Argument.Ty = TInfo;
|
||||
isType = true;
|
||||
}
|
||||
|
||||
@ -1252,7 +1256,7 @@ class MemberExpr : public Expr {
|
||||
|
||||
/// MemberDecl - This is the decl being referenced by the field/member name.
|
||||
/// In X.F, this is the decl referenced by F.
|
||||
NamedDecl *MemberDecl;
|
||||
ValueDecl *MemberDecl;
|
||||
|
||||
/// MemberLoc - This is the location of the member name.
|
||||
SourceLocation MemberLoc;
|
||||
@ -1305,12 +1309,12 @@ class MemberExpr : public Expr {
|
||||
}
|
||||
|
||||
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
|
||||
SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l,
|
||||
const TemplateArgumentListInfo *targs, QualType ty);
|
||||
|
||||
public:
|
||||
MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
|
||||
QualType ty)
|
||||
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
|
||||
SourceLocation l, QualType ty)
|
||||
: Expr(MemberExprClass, ty,
|
||||
base->isTypeDependent(), base->isValueDependent()),
|
||||
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
|
||||
@ -1323,7 +1327,7 @@ class MemberExpr : public Expr {
|
||||
|
||||
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
|
||||
NestedNameSpecifier *qual, SourceRange qualrange,
|
||||
NamedDecl *memberdecl,
|
||||
ValueDecl *memberdecl,
|
||||
SourceLocation l,
|
||||
const TemplateArgumentListInfo *targs,
|
||||
QualType ty);
|
||||
@ -1335,8 +1339,8 @@ class MemberExpr : public Expr {
|
||||
///
|
||||
/// The returned declaration will either be a FieldDecl or (in C++)
|
||||
/// a CXXMethodDecl.
|
||||
NamedDecl *getMemberDecl() const { return MemberDecl; }
|
||||
void setMemberDecl(NamedDecl *D) { MemberDecl = D; }
|
||||
ValueDecl *getMemberDecl() const { return MemberDecl; }
|
||||
void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
|
||||
|
||||
/// \brief Determines whether this member expression actually had
|
||||
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
|
||||
@ -1576,7 +1580,14 @@ class CastExpr : public Expr {
|
||||
CK_FloatingCast,
|
||||
|
||||
/// CK_MemberPointerToBoolean - Member pointer to boolean
|
||||
CK_MemberPointerToBoolean
|
||||
CK_MemberPointerToBoolean,
|
||||
|
||||
/// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
|
||||
/// pointer
|
||||
CK_AnyPointerToObjCPointerCast,
|
||||
/// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
|
||||
/// pointer
|
||||
CK_AnyPointerToBlockPointerCast
|
||||
|
||||
};
|
||||
|
||||
@ -1607,6 +1618,14 @@ class CastExpr : public Expr {
|
||||
const Expr *getSubExpr() const { return cast<Expr>(Op); }
|
||||
void setSubExpr(Expr *E) { Op = E; }
|
||||
|
||||
/// \brief Retrieve the cast subexpression as it was written in the source
|
||||
/// code, looking through any implicit casts or other intermediate nodes
|
||||
/// introduced by semantic analysis.
|
||||
Expr *getSubExprAsWritten();
|
||||
const Expr *getSubExprAsWritten() const {
|
||||
return const_cast<CastExpr *>(this)->getSubExprAsWritten();
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
StmtClass SC = T->getStmtClass();
|
||||
if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass)
|
||||
|
@ -527,6 +527,7 @@ class CXXConstructExpr : public Expr {
|
||||
const_arg_iterator arg_begin() const { return Args; }
|
||||
const_arg_iterator arg_end() const { return Args + NumArgs; }
|
||||
|
||||
Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); }
|
||||
unsigned getNumArgs() const { return NumArgs; }
|
||||
|
||||
/// getArg - Return the specified argument.
|
||||
@ -1410,18 +1411,26 @@ class CXXUnresolvedConstructExpr : public Expr {
|
||||
/// \brief Represents a C++ member access expression where the actual
|
||||
/// member referenced could not be resolved because the base
|
||||
/// expression or the member name was dependent.
|
||||
///
|
||||
/// Like UnresolvedMemberExprs, these can be either implicit or
|
||||
/// explicit accesses. It is only possible to get one of these with
|
||||
/// an implicit access if a qualifier is provided.
|
||||
class CXXDependentScopeMemberExpr : public Expr {
|
||||
/// \brief The expression for the base pointer or class reference,
|
||||
/// e.g., the \c x in x.f.
|
||||
/// e.g., the \c x in x.f. Can be null in implicit accesses.
|
||||
Stmt *Base;
|
||||
|
||||
/// \brief The type of the base expression. Never null, even for
|
||||
/// implicit accesses.
|
||||
QualType BaseType;
|
||||
|
||||
/// \brief Whether this member expression used the '->' operator or
|
||||
/// the '.' operator.
|
||||
bool IsArrow : 1;
|
||||
|
||||
/// \brief Whether this member expression has explicitly-specified template
|
||||
/// arguments.
|
||||
bool HasExplicitTemplateArgumentList : 1;
|
||||
bool HasExplicitTemplateArgs : 1;
|
||||
|
||||
/// \brief The location of the '->' or '.' operator.
|
||||
SourceLocation OperatorLoc;
|
||||
@ -1452,9 +1461,7 @@ class CXXDependentScopeMemberExpr : public Expr {
|
||||
/// \brief Retrieve the explicit template argument list that followed the
|
||||
/// member template name, if any.
|
||||
ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
|
||||
if (!HasExplicitTemplateArgumentList)
|
||||
return 0;
|
||||
|
||||
assert(HasExplicitTemplateArgs);
|
||||
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
|
||||
}
|
||||
|
||||
@ -1466,7 +1473,7 @@ class CXXDependentScopeMemberExpr : public Expr {
|
||||
}
|
||||
|
||||
CXXDependentScopeMemberExpr(ASTContext &C,
|
||||
Expr *Base, bool IsArrow,
|
||||
Expr *Base, QualType BaseType, bool IsArrow,
|
||||
SourceLocation OperatorLoc,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
@ -1477,7 +1484,8 @@ class CXXDependentScopeMemberExpr : public Expr {
|
||||
|
||||
public:
|
||||
CXXDependentScopeMemberExpr(ASTContext &C,
|
||||
Expr *Base, bool IsArrow,
|
||||
Expr *Base, QualType BaseType,
|
||||
bool IsArrow,
|
||||
SourceLocation OperatorLoc,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
@ -1485,15 +1493,15 @@ class CXXDependentScopeMemberExpr : public Expr {
|
||||
DeclarationName Member,
|
||||
SourceLocation MemberLoc)
|
||||
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
|
||||
Base(Base), IsArrow(IsArrow), HasExplicitTemplateArgumentList(false),
|
||||
OperatorLoc(OperatorLoc),
|
||||
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
|
||||
HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc),
|
||||
Qualifier(Qualifier), QualifierRange(QualifierRange),
|
||||
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
|
||||
Member(Member), MemberLoc(MemberLoc) { }
|
||||
|
||||
static CXXDependentScopeMemberExpr *
|
||||
Create(ASTContext &C,
|
||||
Expr *Base, bool IsArrow,
|
||||
Expr *Base, QualType BaseType, bool IsArrow,
|
||||
SourceLocation OperatorLoc,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
@ -1502,11 +1510,21 @@ class CXXDependentScopeMemberExpr : public Expr {
|
||||
SourceLocation MemberLoc,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
/// \brief True if this is an implicit access, i.e. one in which the
|
||||
/// member being accessed was not written in the source. The source
|
||||
/// location of the operator is invalid in this case.
|
||||
bool isImplicitAccess() const { return Base == 0; }
|
||||
|
||||
/// \brief Retrieve the base object of this member expressions,
|
||||
/// e.g., the \c x in \c x.m.
|
||||
Expr *getBase() { return cast<Expr>(Base); }
|
||||
Expr *getBase() const {
|
||||
assert(!isImplicitAccess());
|
||||
return cast<Expr>(Base);
|
||||
}
|
||||
void setBase(Expr *E) { Base = E; }
|
||||
|
||||
QualType getBaseType() const { return BaseType; }
|
||||
|
||||
/// \brief Determine whether this member expression used the '->'
|
||||
/// operator; otherwise, it used the '.' operator.
|
||||
bool isArrow() const { return IsArrow; }
|
||||
@ -1551,60 +1569,59 @@ class CXXDependentScopeMemberExpr : public Expr {
|
||||
|
||||
/// \brief Determines whether this member expression actually had a C++
|
||||
/// template argument list explicitly specified, e.g., x.f<int>.
|
||||
bool hasExplicitTemplateArgumentList() const {
|
||||
return HasExplicitTemplateArgumentList;
|
||||
bool hasExplicitTemplateArgs() const {
|
||||
return HasExplicitTemplateArgs;
|
||||
}
|
||||
|
||||
/// \brief Copies the template arguments (if present) into the given
|
||||
/// structure.
|
||||
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
|
||||
if (hasExplicitTemplateArgumentList())
|
||||
getExplicitTemplateArgumentList()->copyInto(List);
|
||||
assert(HasExplicitTemplateArgs);
|
||||
getExplicitTemplateArgumentList()->copyInto(List);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the left angle bracket following the
|
||||
/// member name ('<'), if any.
|
||||
SourceLocation getLAngleLoc() const {
|
||||
if (!HasExplicitTemplateArgumentList)
|
||||
return SourceLocation();
|
||||
|
||||
assert(HasExplicitTemplateArgs);
|
||||
return getExplicitTemplateArgumentList()->LAngleLoc;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template arguments provided as part of this
|
||||
/// template-id.
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
if (!HasExplicitTemplateArgumentList)
|
||||
return 0;
|
||||
|
||||
assert(HasExplicitTemplateArgs);
|
||||
return getExplicitTemplateArgumentList()->getTemplateArgs();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the number of template arguments provided as part of this
|
||||
/// template-id.
|
||||
unsigned getNumTemplateArgs() const {
|
||||
if (!HasExplicitTemplateArgumentList)
|
||||
return 0;
|
||||
|
||||
assert(HasExplicitTemplateArgs);
|
||||
return getExplicitTemplateArgumentList()->NumTemplateArgs;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the right angle bracket following the
|
||||
/// template arguments ('>').
|
||||
SourceLocation getRAngleLoc() const {
|
||||
if (!HasExplicitTemplateArgumentList)
|
||||
return SourceLocation();
|
||||
|
||||
assert(HasExplicitTemplateArgs);
|
||||
return getExplicitTemplateArgumentList()->RAngleLoc;
|
||||
}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
if (HasExplicitTemplateArgumentList)
|
||||
return SourceRange(Base->getSourceRange().getBegin(),
|
||||
getRAngleLoc());
|
||||
SourceRange Range;
|
||||
if (!isImplicitAccess())
|
||||
Range.setBegin(Base->getSourceRange().getBegin());
|
||||
else if (getQualifier())
|
||||
Range.setBegin(getQualifierRange().getBegin());
|
||||
else
|
||||
Range.setBegin(MemberLoc);
|
||||
|
||||
return SourceRange(Base->getSourceRange().getBegin(),
|
||||
MemberLoc);
|
||||
if (hasExplicitTemplateArgs())
|
||||
Range.setEnd(getRAngleLoc());
|
||||
else
|
||||
Range.setEnd(MemberLoc);
|
||||
return Range;
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
@ -1618,17 +1635,31 @@ class CXXDependentScopeMemberExpr : public Expr {
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ member access expression for which lookup
|
||||
/// produced a set of overloaded functions. These are replaced with
|
||||
/// MemberExprs in the final AST.
|
||||
/// produced a set of overloaded functions.
|
||||
///
|
||||
/// The member access may be explicit or implicit:
|
||||
/// struct A {
|
||||
/// int a, b;
|
||||
/// int explicitAccess() { return this->a + this->A::b; }
|
||||
/// int implicitAccess() { return a + A::b; }
|
||||
/// };
|
||||
///
|
||||
/// In the final AST, an explicit access always becomes a MemberExpr.
|
||||
/// An implicit access may become either a MemberExpr or a
|
||||
/// DeclRefExpr, depending on whether the member is static.
|
||||
class UnresolvedMemberExpr : public Expr {
|
||||
/// The results. These are undesugared, which is to say, they may
|
||||
/// include UsingShadowDecls.
|
||||
UnresolvedSet Results;
|
||||
|
||||
/// \brief The expression for the base pointer or class reference,
|
||||
/// e.g., the \c x in x.f.
|
||||
/// e.g., the \c x in x.f. This can be null if this is an 'unbased'
|
||||
/// member expression
|
||||
Stmt *Base;
|
||||
|
||||
/// \brief The type of the base expression; never null.
|
||||
QualType BaseType;
|
||||
|
||||
/// \brief Whether this member expression used the '->' operator or
|
||||
/// the '.' operator.
|
||||
bool IsArrow : 1;
|
||||
@ -1672,7 +1703,7 @@ class UnresolvedMemberExpr : public Expr {
|
||||
|
||||
UnresolvedMemberExpr(QualType T, bool Dependent,
|
||||
bool HasUnresolvedUsing,
|
||||
Expr *Base, bool IsArrow,
|
||||
Expr *Base, QualType BaseType, bool IsArrow,
|
||||
SourceLocation OperatorLoc,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
@ -1683,7 +1714,7 @@ class UnresolvedMemberExpr : public Expr {
|
||||
public:
|
||||
static UnresolvedMemberExpr *
|
||||
Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing,
|
||||
Expr *Base, bool IsArrow,
|
||||
Expr *Base, QualType BaseType, bool IsArrow,
|
||||
SourceLocation OperatorLoc,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
@ -1704,11 +1735,21 @@ class UnresolvedMemberExpr : public Expr {
|
||||
|
||||
unsigned getNumDecls() const { return Results.size(); }
|
||||
|
||||
/// \brief True if this is an implicit access, i.e. one in which the
|
||||
/// member being accessed was not written in the source. The source
|
||||
/// location of the operator is invalid in this case.
|
||||
bool isImplicitAccess() const { return Base == 0; }
|
||||
|
||||
/// \brief Retrieve the base object of this member expressions,
|
||||
/// e.g., the \c x in \c x.m.
|
||||
Expr *getBase() { return cast<Expr>(Base); }
|
||||
Expr *getBase() {
|
||||
assert(!isImplicitAccess());
|
||||
return cast<Expr>(Base);
|
||||
}
|
||||
void setBase(Expr *E) { Base = E; }
|
||||
|
||||
QualType getBaseType() const { return BaseType; }
|
||||
|
||||
/// \brief Determine whether this member expression used the '->'
|
||||
/// operator; otherwise, it used the '.' operator.
|
||||
bool isArrow() const { return IsArrow; }
|
||||
@ -1772,7 +1813,14 @@ class UnresolvedMemberExpr : public Expr {
|
||||
}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
SourceRange Range = Base->getSourceRange();
|
||||
SourceRange Range;
|
||||
if (!isImplicitAccess())
|
||||
Range.setBegin(Base->getSourceRange().getBegin());
|
||||
else if (getQualifier())
|
||||
Range.setBegin(getQualifierRange().getBegin());
|
||||
else
|
||||
Range.setBegin(MemberLoc);
|
||||
|
||||
if (hasExplicitTemplateArgs())
|
||||
Range.setEnd(getRAngleLoc());
|
||||
else
|
||||
|
@ -119,13 +119,6 @@ class ASTRecordLayout {
|
||||
/// VBaseOffsets - Contains a map from vbase classes to their offset.
|
||||
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
|
||||
llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets;
|
||||
|
||||
/// KeyFunction - The key function, according to the Itanium C++ ABI,
|
||||
/// section 5.2.3:
|
||||
///
|
||||
/// ...the first non-pure virtual function that is not inline at the point
|
||||
/// of class definition.
|
||||
const CXXMethodDecl *KeyFunction;
|
||||
};
|
||||
|
||||
/// CXXInfo - If the record layout is for a C++ record, this will have
|
||||
@ -154,8 +147,7 @@ class ASTRecordLayout {
|
||||
const std::pair<const CXXRecordDecl *, uint64_t> *bases,
|
||||
unsigned numbases,
|
||||
const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
|
||||
unsigned numvbases,
|
||||
const CXXMethodDecl *KeyFunction)
|
||||
unsigned numvbases)
|
||||
: Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
|
||||
FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) {
|
||||
if (FieldCount > 0) {
|
||||
@ -171,7 +163,6 @@ class ASTRecordLayout {
|
||||
CXXInfo->BaseOffsets[bases[i].first] = bases[i].second;
|
||||
for (unsigned i = 0; i != numvbases; ++i)
|
||||
CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second;
|
||||
CXXInfo->KeyFunction = KeyFunction;
|
||||
}
|
||||
|
||||
~ASTRecordLayout() {
|
||||
@ -254,13 +245,6 @@ class ASTRecordLayout {
|
||||
return CXXInfo->VBaseOffsets[VBase];
|
||||
}
|
||||
|
||||
/// getKeyFunction - Get the key function.
|
||||
const CXXMethodDecl *getKeyFunction() const {
|
||||
assert(CXXInfo && "Record layout does not have C++ specific info!");
|
||||
|
||||
return CXXInfo->KeyFunction;
|
||||
}
|
||||
|
||||
primary_base_info_iterator primary_base_begin() const {
|
||||
assert(CXXInfo && "Record layout does not have C++ specific info!");
|
||||
|
||||
|
@ -68,10 +68,11 @@ class CXXTryStmt : public Stmt {
|
||||
Stmt **handlers, unsigned numHandlers);
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(TryLoc, Stmts.back()->getLocEnd());
|
||||
return SourceRange(getTryLoc(), getEndLoc());
|
||||
}
|
||||
|
||||
SourceLocation getTryLoc() const { return TryLoc; }
|
||||
SourceLocation getEndLoc() const { return Stmts.back()->getLocEnd(); }
|
||||
|
||||
CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); }
|
||||
const CompoundStmt *getTryBlock() const {
|
||||
|
@ -29,7 +29,7 @@ namespace clang {
|
||||
|
||||
class Decl;
|
||||
class Expr;
|
||||
class DeclaratorInfo;
|
||||
class TypeSourceInfo;
|
||||
|
||||
/// \brief Represents a template argument within a class template
|
||||
/// specialization.
|
||||
@ -267,7 +267,7 @@ struct TemplateArgumentLocInfo {
|
||||
private:
|
||||
union {
|
||||
Expr *Expression;
|
||||
DeclaratorInfo *Declarator;
|
||||
TypeSourceInfo *Declarator;
|
||||
struct {
|
||||
unsigned QualifierRange[2];
|
||||
unsigned TemplateNameLoc;
|
||||
@ -277,7 +277,7 @@ struct TemplateArgumentLocInfo {
|
||||
#ifndef NDEBUG
|
||||
enum Kind {
|
||||
K_None,
|
||||
K_DeclaratorInfo,
|
||||
K_TypeSourceInfo,
|
||||
K_Expression,
|
||||
K_Template
|
||||
} Kind;
|
||||
@ -291,10 +291,10 @@ struct TemplateArgumentLocInfo {
|
||||
#endif
|
||||
{}
|
||||
|
||||
TemplateArgumentLocInfo(DeclaratorInfo *DInfo)
|
||||
: Declarator(DInfo)
|
||||
TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
|
||||
: Declarator(TInfo)
|
||||
#ifndef NDEBUG
|
||||
, Kind(K_DeclaratorInfo)
|
||||
, Kind(K_TypeSourceInfo)
|
||||
#endif
|
||||
{}
|
||||
|
||||
@ -316,8 +316,8 @@ struct TemplateArgumentLocInfo {
|
||||
Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
|
||||
}
|
||||
|
||||
DeclaratorInfo *getAsDeclaratorInfo() const {
|
||||
assert(Kind == K_DeclaratorInfo);
|
||||
TypeSourceInfo *getAsTypeSourceInfo() const {
|
||||
assert(Kind == K_TypeSourceInfo);
|
||||
return Declarator;
|
||||
}
|
||||
|
||||
@ -342,7 +342,7 @@ struct TemplateArgumentLocInfo {
|
||||
void validateForArgument(const TemplateArgument &Arg) {
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Type:
|
||||
assert(Kind == K_DeclaratorInfo);
|
||||
assert(Kind == K_TypeSourceInfo);
|
||||
break;
|
||||
case TemplateArgument::Expression:
|
||||
case TemplateArgument::Declaration:
|
||||
@ -356,7 +356,7 @@ struct TemplateArgumentLocInfo {
|
||||
assert(Kind == K_None);
|
||||
break;
|
||||
case TemplateArgument::Null:
|
||||
llvm::llvm_unreachable("source info for null template argument?");
|
||||
llvm_unreachable("source info for null template argument?");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -376,8 +376,8 @@ class TemplateArgumentLoc {
|
||||
: Argument(Argument), LocInfo(Opaque) {
|
||||
}
|
||||
|
||||
TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo)
|
||||
: Argument(Argument), LocInfo(DInfo) {
|
||||
TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
|
||||
: Argument(Argument), LocInfo(TInfo) {
|
||||
assert(Argument.getKind() == TemplateArgument::Type);
|
||||
}
|
||||
|
||||
@ -412,9 +412,9 @@ class TemplateArgumentLoc {
|
||||
return LocInfo;
|
||||
}
|
||||
|
||||
DeclaratorInfo *getSourceDeclaratorInfo() const {
|
||||
TypeSourceInfo *getTypeSourceInfo() const {
|
||||
assert(Argument.getKind() == TemplateArgument::Type);
|
||||
return LocInfo.getAsDeclaratorInfo();
|
||||
return LocInfo.getAsTypeSourceInfo();
|
||||
}
|
||||
|
||||
Expr *getSourceExpression() const {
|
||||
|
@ -31,7 +31,34 @@ struct PrintingPolicy;
|
||||
class QualifiedTemplateName;
|
||||
class NamedDecl;
|
||||
class TemplateDecl;
|
||||
class OverloadedFunctionDecl;
|
||||
|
||||
/// \brief A structure for storing the information associated with an
|
||||
/// overloaded template name.
|
||||
class OverloadedTemplateStorage {
|
||||
union {
|
||||
unsigned Size;
|
||||
NamedDecl *Storage[1];
|
||||
};
|
||||
|
||||
friend class ASTContext;
|
||||
|
||||
OverloadedTemplateStorage(unsigned Size) : Size(Size) {}
|
||||
|
||||
NamedDecl **getStorage() {
|
||||
return &Storage[1];
|
||||
}
|
||||
NamedDecl * const *getStorage() const {
|
||||
return &Storage[1];
|
||||
}
|
||||
|
||||
public:
|
||||
typedef NamedDecl *const *iterator;
|
||||
|
||||
unsigned size() const { return Size; }
|
||||
|
||||
iterator begin() const { return getStorage(); }
|
||||
iterator end() const { return getStorage() + size(); }
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ template name within the type system.
|
||||
///
|
||||
@ -61,7 +88,8 @@ class OverloadedFunctionDecl;
|
||||
/// specifier in the typedef. "apply" is a nested template, and can
|
||||
/// only be understood in the context of
|
||||
class TemplateName {
|
||||
typedef llvm::PointerUnion4<TemplateDecl *, OverloadedFunctionDecl *,
|
||||
typedef llvm::PointerUnion4<TemplateDecl *,
|
||||
OverloadedTemplateStorage *,
|
||||
QualifiedTemplateName *,
|
||||
DependentTemplateName *> StorageType;
|
||||
|
||||
@ -74,8 +102,8 @@ class TemplateName {
|
||||
public:
|
||||
TemplateName() : Storage() { }
|
||||
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
|
||||
explicit TemplateName(OverloadedFunctionDecl *FunctionTemplates)
|
||||
: Storage(FunctionTemplates) { }
|
||||
explicit TemplateName(OverloadedTemplateStorage *Storage)
|
||||
: Storage(Storage) { }
|
||||
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
|
||||
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
|
||||
|
||||
@ -98,7 +126,9 @@ class TemplateName {
|
||||
/// name refers to, if known. If the template name does not refer to a
|
||||
/// specific set of function templates because it is a dependent name or
|
||||
/// refers to a single template, returns NULL.
|
||||
OverloadedFunctionDecl *getAsOverloadedFunctionDecl() const;
|
||||
OverloadedTemplateStorage *getAsOverloadedTemplate() const {
|
||||
return Storage.dyn_cast<OverloadedTemplateStorage *>();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the underlying qualified template name
|
||||
/// structure, if any.
|
||||
@ -166,19 +196,14 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
|
||||
|
||||
/// \brief The template declaration or set of overloaded function templates
|
||||
/// that this qualified name refers to.
|
||||
NamedDecl *Template;
|
||||
TemplateDecl *Template;
|
||||
|
||||
friend class ASTContext;
|
||||
|
||||
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
|
||||
TemplateDecl *Template)
|
||||
: Qualifier(NNS, TemplateKeyword? 1 : 0),
|
||||
Template(reinterpret_cast<NamedDecl *>(Template)) { }
|
||||
|
||||
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
|
||||
OverloadedFunctionDecl *Template)
|
||||
: Qualifier(NNS, TemplateKeyword? 1 : 0),
|
||||
Template(reinterpret_cast<NamedDecl *>(Template)) { }
|
||||
Template(Template) { }
|
||||
|
||||
public:
|
||||
/// \brief Return the nested name specifier that qualifies this name.
|
||||
@ -188,26 +213,20 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
|
||||
/// keyword.
|
||||
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
|
||||
|
||||
/// \brief The template declaration or set of overloaded functions that
|
||||
/// that qualified name refers to.
|
||||
NamedDecl *getDecl() const { return Template; }
|
||||
/// \brief The template declaration that this qualified name refers
|
||||
/// to.
|
||||
TemplateDecl *getDecl() const { return Template; }
|
||||
|
||||
/// \brief The template declaration to which this qualified name
|
||||
/// refers, or NULL if this qualified name refers to a set of overloaded
|
||||
/// function templates.
|
||||
TemplateDecl *getTemplateDecl() const;
|
||||
|
||||
/// \brief The set of overloaded function tempaltes to which this qualified
|
||||
/// name refers, or NULL if this qualified name refers to a single
|
||||
/// template declaration.
|
||||
OverloadedFunctionDecl *getOverloadedFunctionDecl() const;
|
||||
/// refers.
|
||||
TemplateDecl *getTemplateDecl() const { return Template; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getQualifier(), hasTemplateKeyword(), getDecl());
|
||||
Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword, NamedDecl *Template) {
|
||||
bool TemplateKeyword, TemplateDecl *Template) {
|
||||
ID.AddPointer(NNS);
|
||||
ID.AddBoolean(TemplateKeyword);
|
||||
ID.AddPointer(Template);
|
||||
|
@ -35,7 +35,9 @@ namespace clang {
|
||||
TypeAlignmentInBits = 3,
|
||||
TypeAlignment = 1 << TypeAlignmentInBits
|
||||
};
|
||||
class Type; class ExtQuals;
|
||||
class Type;
|
||||
class ExtQuals;
|
||||
class QualType;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
@ -59,6 +61,9 @@ namespace llvm {
|
||||
}
|
||||
enum { NumLowBitsAvailable = clang::TypeAlignmentInBits };
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::QualType> { static const bool value = true; };
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
@ -76,6 +81,7 @@ namespace clang {
|
||||
class ObjCInterfaceDecl;
|
||||
class ObjCProtocolDecl;
|
||||
class ObjCMethodDecl;
|
||||
class UnresolvedUsingTypenameDecl;
|
||||
class Expr;
|
||||
class Stmt;
|
||||
class SourceLocation;
|
||||
@ -791,6 +797,10 @@ class Type {
|
||||
/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
|
||||
bool isPODType() const;
|
||||
|
||||
/// isLiteralType - Return true if this is a literal type
|
||||
/// (C++0x [basic.types]p10)
|
||||
bool isLiteralType() const;
|
||||
|
||||
/// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
|
||||
/// types that have a non-constant expression. This does not include "[]".
|
||||
bool isVariablyModifiedType() const;
|
||||
@ -808,8 +818,9 @@ class Type {
|
||||
bool isBooleanType() const;
|
||||
bool isCharType() const;
|
||||
bool isWideCharType() const;
|
||||
bool isAnyCharacterType() const;
|
||||
bool isIntegralType() const;
|
||||
|
||||
|
||||
/// Floating point categories.
|
||||
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
|
||||
/// isComplexType() does *not* include complex integers (a GCC extension).
|
||||
@ -1859,6 +1870,38 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
|
||||
};
|
||||
|
||||
|
||||
/// \brief Represents the dependent type named by a dependently-scoped
|
||||
/// typename using declaration, e.g.
|
||||
/// using typename Base<T>::foo;
|
||||
/// Template instantiation turns these into the underlying type.
|
||||
class UnresolvedUsingType : public Type {
|
||||
UnresolvedUsingTypenameDecl *Decl;
|
||||
|
||||
UnresolvedUsingType(UnresolvedUsingTypenameDecl *D)
|
||||
: Type(UnresolvedUsing, QualType(), true), Decl(D) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
UnresolvedUsingTypenameDecl *getDecl() const { return Decl; }
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == UnresolvedUsing;
|
||||
}
|
||||
static bool classof(const UnresolvedUsingType *) { return true; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
return Profile(ID, Decl);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
UnresolvedUsingTypenameDecl *D) {
|
||||
ID.AddPointer(D);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TypedefType : public Type {
|
||||
TypedefDecl *Decl;
|
||||
protected:
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
namespace clang {
|
||||
class ParmVarDecl;
|
||||
class DeclaratorInfo;
|
||||
class TypeSourceInfo;
|
||||
class UnqualTypeLoc;
|
||||
|
||||
// Predeclare all the type nodes.
|
||||
@ -340,16 +340,20 @@ class InheritingConcreteTypeLoc : public Base {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct TypeSpecLocInfo {
|
||||
SourceLocation NameLoc;
|
||||
};
|
||||
|
||||
/// \brief A reasonable base class for TypeLocs that correspond to
|
||||
/// types that are written as a type-specifier.
|
||||
template <class Derived, class TypeClass, class LocalData = TypeSpecLocInfo>
|
||||
class TypeSpecTypeLoc
|
||||
: public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
|
||||
class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
TypeSpecTypeLoc,
|
||||
Type,
|
||||
TypeSpecLocInfo> {
|
||||
public:
|
||||
enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
|
||||
|
||||
SourceLocation getNameLoc() const {
|
||||
return this->getLocalData()->NameLoc;
|
||||
}
|
||||
@ -362,31 +366,79 @@ class TypeSpecTypeLoc
|
||||
void initializeLocal(SourceLocation Loc) {
|
||||
setNameLoc(Loc);
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const TypeSpecTypeLoc *TL) { return true; }
|
||||
};
|
||||
|
||||
|
||||
/// \brief Wrapper for source info for typedefs.
|
||||
class TypedefTypeLoc : public TypeSpecTypeLoc<TypedefTypeLoc,TypedefType> {
|
||||
class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
TypedefTypeLoc,
|
||||
TypedefType> {
|
||||
public:
|
||||
TypedefDecl *getTypedefDecl() const {
|
||||
return getTypePtr()->getDecl();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for unresolved typename using decls.
|
||||
class UnresolvedUsingTypeLoc :
|
||||
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
UnresolvedUsingTypeLoc,
|
||||
UnresolvedUsingType> {
|
||||
public:
|
||||
UnresolvedUsingTypenameDecl *getDecl() const {
|
||||
return getTypePtr()->getDecl();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for tag types. Note that this only
|
||||
/// records source info for the name itself; a type written 'struct foo'
|
||||
/// should be represented as an ElaboratedTypeLoc. We currently
|
||||
/// only do that when C++ is enabled because of the expense of
|
||||
/// creating an ElaboratedType node for so many type references in C.
|
||||
class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
TagTypeLoc,
|
||||
TagType> {
|
||||
public:
|
||||
TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for record types.
|
||||
class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
|
||||
RecordTypeLoc,
|
||||
RecordType> {
|
||||
public:
|
||||
RecordDecl *getDecl() const { return getTypePtr()->getDecl(); }
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for enum types.
|
||||
class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
|
||||
EnumTypeLoc,
|
||||
EnumType> {
|
||||
public:
|
||||
EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for builtin types.
|
||||
class BuiltinTypeLoc : public TypeSpecTypeLoc<BuiltinTypeLoc,
|
||||
BuiltinType> {
|
||||
class BuiltinTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
BuiltinTypeLoc,
|
||||
BuiltinType> {
|
||||
};
|
||||
|
||||
/// \brief Wrapper for template type parameters.
|
||||
class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc,
|
||||
TemplateTypeParmType> {
|
||||
class TemplateTypeParmTypeLoc :
|
||||
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
TemplateTypeParmTypeLoc,
|
||||
TemplateTypeParmType> {
|
||||
};
|
||||
|
||||
/// \brief Wrapper for substituted template type parameters.
|
||||
class SubstTemplateTypeParmTypeLoc :
|
||||
public TypeSpecTypeLoc<SubstTemplateTypeParmTypeLoc,
|
||||
SubstTemplateTypeParmType> {
|
||||
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
SubstTemplateTypeParmTypeLoc,
|
||||
SubstTemplateTypeParmType> {
|
||||
};
|
||||
|
||||
|
||||
@ -889,7 +941,7 @@ class TemplateSpecializationTypeLoc :
|
||||
assert(size == Loc.getFullDataSize());
|
||||
|
||||
// We're potentially copying Expr references here. We don't
|
||||
// bother retaining them because DeclaratorInfos live forever, so
|
||||
// bother retaining them because TypeSourceInfos live forever, so
|
||||
// as long as the Expr was retained when originally written into
|
||||
// the TypeLoc, we're okay.
|
||||
memcpy(Data, Loc.Data, size);
|
||||
@ -916,7 +968,7 @@ class TemplateSpecializationTypeLoc :
|
||||
break;
|
||||
|
||||
case TemplateArgument::Type:
|
||||
Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
|
||||
Info = TemplateArgumentLocInfo((TypeSourceInfo*) 0);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Template:
|
||||
@ -944,63 +996,84 @@ class TemplateSpecializationTypeLoc :
|
||||
}
|
||||
};
|
||||
|
||||
// None of these types have proper implementations yet.
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// All of these need proper implementations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> {
|
||||
// FIXME: size expression and attribute locations (or keyword if we
|
||||
// ever fully support altivec syntax).
|
||||
class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
VectorTypeLoc,
|
||||
VectorType> {
|
||||
};
|
||||
|
||||
// FIXME: size expression and attribute locations.
|
||||
class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
|
||||
ExtVectorTypeLoc,
|
||||
ExtVectorType> {
|
||||
};
|
||||
|
||||
// FIXME: attribute locations.
|
||||
// For some reason, this isn't a subtype of VectorType.
|
||||
class DependentSizedExtVectorTypeLoc :
|
||||
public TypeSpecTypeLoc<DependentSizedExtVectorTypeLoc,
|
||||
DependentSizedExtVectorType> {
|
||||
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
DependentSizedExtVectorTypeLoc,
|
||||
DependentSizedExtVectorType> {
|
||||
};
|
||||
|
||||
class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc,
|
||||
FixedWidthIntType> {
|
||||
// FIXME: I'm not sure how you actually specify these; with attributes?
|
||||
class FixedWidthIntTypeLoc :
|
||||
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
FixedWidthIntTypeLoc,
|
||||
FixedWidthIntType> {
|
||||
};
|
||||
|
||||
class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc,
|
||||
ComplexType> {
|
||||
// FIXME: location of the '_Complex' keyword.
|
||||
class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
ComplexTypeLoc,
|
||||
ComplexType> {
|
||||
};
|
||||
|
||||
class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc,
|
||||
TypeOfExprType> {
|
||||
// FIXME: location of the 'typeof' and parens (the expression is
|
||||
// carried by the type).
|
||||
class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
TypeOfExprTypeLoc,
|
||||
TypeOfExprType> {
|
||||
};
|
||||
|
||||
class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> {
|
||||
// FIXME: location of the 'typeof' and parens; also the TypeSourceInfo
|
||||
// for the inner type, or (maybe) just express that inline to the TypeLoc.
|
||||
class TypeOfTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
TypeOfTypeLoc,
|
||||
TypeOfType> {
|
||||
};
|
||||
|
||||
class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> {
|
||||
// FIXME: location of the 'decltype' and parens.
|
||||
class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
DecltypeTypeLoc,
|
||||
DecltypeType> {
|
||||
};
|
||||
|
||||
class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> {
|
||||
// FIXME: location of the tag keyword.
|
||||
class ElaboratedTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
ElaboratedTypeLoc,
|
||||
ElaboratedType> {
|
||||
};
|
||||
|
||||
class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
|
||||
RecordTypeLoc,
|
||||
RecordType> {
|
||||
// FIXME: locations for the nested name specifier; at the very least,
|
||||
// a SourceRange.
|
||||
class QualifiedNameTypeLoc :
|
||||
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
QualifiedNameTypeLoc,
|
||||
QualifiedNameType> {
|
||||
};
|
||||
|
||||
class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
|
||||
EnumTypeLoc,
|
||||
EnumType> {
|
||||
};
|
||||
|
||||
class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc,
|
||||
ElaboratedType> {
|
||||
};
|
||||
|
||||
class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc,
|
||||
QualifiedNameType> {
|
||||
};
|
||||
|
||||
class TypenameTypeLoc : public TypeSpecTypeLoc<TypenameTypeLoc,
|
||||
TypenameType> {
|
||||
// FIXME: locations for the typename keyword and nested name specifier.
|
||||
class TypenameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
TypenameTypeLoc,
|
||||
TypenameType> {
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -59,9 +59,35 @@ class TypeLocBuilder {
|
||||
grow(Requested);
|
||||
}
|
||||
|
||||
/// Pushes space for a new TypeLoc onto the given type. Invalidates
|
||||
/// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
|
||||
/// previously retrieved from this builder.
|
||||
TypeSpecTypeLoc pushTypeSpec(QualType T) {
|
||||
size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
|
||||
return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
|
||||
}
|
||||
|
||||
|
||||
/// Pushes space for a new TypeLoc of the given type. Invalidates
|
||||
/// any TypeLocs previously retrieved from this builder.
|
||||
template <class TyLocType> TyLocType push(QualType T) {
|
||||
size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
|
||||
return cast<TyLocType>(pushImpl(T, LocalSize));
|
||||
}
|
||||
|
||||
/// Creates a TypeSourceInfo for the given type.
|
||||
TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
|
||||
#ifndef NDEBUG
|
||||
assert(T == LastTy && "type doesn't match last type pushed!");
|
||||
#endif
|
||||
|
||||
size_t FullDataSize = Capacity - Index;
|
||||
TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
|
||||
memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
|
||||
return DI;
|
||||
}
|
||||
|
||||
private:
|
||||
TypeLoc pushImpl(QualType T, size_t LocalSize) {
|
||||
#ifndef NDEBUG
|
||||
QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
|
||||
assert(TLast == LastTy &&
|
||||
@ -69,8 +95,6 @@ class TypeLocBuilder {
|
||||
LastTy = T;
|
||||
#endif
|
||||
|
||||
size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
|
||||
|
||||
// If we need to grow, grow by a factor of 2.
|
||||
if (LocalSize > Index) {
|
||||
size_t RequiredCapacity = Capacity + (LocalSize - Index);
|
||||
@ -82,22 +106,9 @@ class TypeLocBuilder {
|
||||
|
||||
Index -= LocalSize;
|
||||
|
||||
return cast<TyLocType>(TypeLoc(T, &Buffer[Index]));
|
||||
return TypeLoc(T, &Buffer[Index]);
|
||||
}
|
||||
|
||||
/// Creates a DeclaratorInfo for the given type.
|
||||
DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) {
|
||||
#ifndef NDEBUG
|
||||
assert(T == LastTy && "type doesn't match last type pushed!");
|
||||
#endif
|
||||
|
||||
size_t FullDataSize = Capacity - Index;
|
||||
DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize);
|
||||
memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
|
||||
return DI;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Grow to the given capacity.
|
||||
void grow(size_t NewCapacity) {
|
||||
assert(NewCapacity > Capacity);
|
||||
|
@ -33,7 +33,7 @@ class TypeLocVisitor {
|
||||
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
}
|
||||
llvm::llvm_unreachable("unexpected type loc class!");
|
||||
llvm_unreachable("unexpected type loc class!");
|
||||
}
|
||||
|
||||
RetTy Visit(UnqualTypeLoc TyLoc) {
|
||||
|
@ -71,6 +71,7 @@ TYPE(ExtVector, VectorType)
|
||||
ABSTRACT_TYPE(Function, Type)
|
||||
TYPE(FunctionProto, FunctionType)
|
||||
TYPE(FunctionNoProto, FunctionType)
|
||||
DEPENDENT_TYPE(UnresolvedUsing, Type)
|
||||
NON_CANONICAL_TYPE(Typedef, Type)
|
||||
NON_CANONICAL_TYPE(TypeOfExpr, Type)
|
||||
NON_CANONICAL_TYPE(TypeOf, Type)
|
||||
|
@ -50,13 +50,6 @@ namespace llvm {
|
||||
static bool isEqual(clang::QualType LHS, clang::QualType RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
|
||||
static bool isPod() {
|
||||
// QualType isn't *technically* a POD type. However, we can get
|
||||
// away with calling it a POD type since its copy constructor,
|
||||
// copy assignment operator, and destructor are all trivial.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -179,9 +179,7 @@ class PathDiagnosticPiece {
|
||||
PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P);
|
||||
|
||||
protected:
|
||||
PathDiagnosticPiece(const std::string& s, Kind k, DisplayHint hint = Below);
|
||||
|
||||
PathDiagnosticPiece(const char* s, Kind k, DisplayHint hint = Below);
|
||||
PathDiagnosticPiece(llvm::StringRef s, Kind k, DisplayHint hint = Below);
|
||||
|
||||
PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
|
||||
|
||||
@ -242,7 +240,7 @@ class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
|
||||
PathDiagnosticLocation Pos;
|
||||
public:
|
||||
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
|
||||
const std::string& s,
|
||||
llvm::StringRef s,
|
||||
PathDiagnosticPiece::Kind k,
|
||||
bool addPosRange = true)
|
||||
: PathDiagnosticPiece(s, k), Pos(pos) {
|
||||
@ -261,11 +259,7 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
|
||||
|
||||
public:
|
||||
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
|
||||
const std::string& s, bool addPosRange = true)
|
||||
: PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
|
||||
|
||||
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, const char* s,
|
||||
bool addPosRange = true)
|
||||
llvm::StringRef s, bool addPosRange = true)
|
||||
: PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
|
||||
|
||||
~PathDiagnosticEventPiece();
|
||||
@ -280,14 +274,7 @@ class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
|
||||
public:
|
||||
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
|
||||
const PathDiagnosticLocation &endPos,
|
||||
const std::string& s)
|
||||
: PathDiagnosticPiece(s, ControlFlow) {
|
||||
LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
|
||||
}
|
||||
|
||||
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
|
||||
const PathDiagnosticLocation &endPos,
|
||||
const char* s)
|
||||
llvm::StringRef s)
|
||||
: PathDiagnosticPiece(s, ControlFlow) {
|
||||
LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
|
||||
}
|
||||
@ -384,22 +371,19 @@ class PathDiagnostic : public llvm::FoldingSetNode {
|
||||
public:
|
||||
PathDiagnostic();
|
||||
|
||||
PathDiagnostic(const char* bugtype, const char* desc, const char* category);
|
||||
|
||||
PathDiagnostic(const std::string& bugtype, const std::string& desc,
|
||||
const std::string& category);
|
||||
PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc,
|
||||
llvm::StringRef category);
|
||||
|
||||
~PathDiagnostic();
|
||||
|
||||
const std::string& getDescription() const { return Desc; }
|
||||
const std::string& getBugType() const { return BugType; }
|
||||
const std::string& getCategory() const { return Category; }
|
||||
llvm::StringRef getDescription() const { return Desc; }
|
||||
llvm::StringRef getBugType() const { return BugType; }
|
||||
llvm::StringRef getCategory() const { return Category; }
|
||||
|
||||
typedef std::deque<std::string>::const_iterator meta_iterator;
|
||||
meta_iterator meta_begin() const { return OtherDesc.begin(); }
|
||||
meta_iterator meta_end() const { return OtherDesc.end(); }
|
||||
void addMeta(const std::string& s) { OtherDesc.push_back(s); }
|
||||
void addMeta(const char* s) { OtherDesc.push_back(s); }
|
||||
void addMeta(llvm::StringRef s) { OtherDesc.push_back(s); }
|
||||
|
||||
PathDiagnosticLocation getLocation() const {
|
||||
assert(Size > 0 && "getLocation() requires a non-empty PathDiagnostic.");
|
||||
|
@ -15,9 +15,10 @@
|
||||
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
|
||||
#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
|
||||
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
@ -29,7 +30,10 @@ class CFG;
|
||||
class LiveVariables;
|
||||
class ParentMap;
|
||||
class ImplicitParamDecl;
|
||||
|
||||
class LocationContextManager;
|
||||
class BlockDataRegion;
|
||||
class StackFrameContext;
|
||||
|
||||
/// AnalysisContext contains the context data for the function or method under
|
||||
/// analysis.
|
||||
class AnalysisContext {
|
||||
@ -78,7 +82,7 @@ class AnalysisContextManager {
|
||||
|
||||
class LocationContext : public llvm::FoldingSetNode {
|
||||
public:
|
||||
enum ContextKind { StackFrame, Scope };
|
||||
enum ContextKind { StackFrame, Scope, Block };
|
||||
|
||||
private:
|
||||
ContextKind Kind;
|
||||
@ -91,7 +95,7 @@ class LocationContext : public llvm::FoldingSetNode {
|
||||
: Kind(k), Ctx(ctx), Parent(parent) {}
|
||||
|
||||
public:
|
||||
virtual ~LocationContext() {}
|
||||
virtual ~LocationContext();
|
||||
|
||||
ContextKind getKind() const { return Kind; }
|
||||
|
||||
@ -114,36 +118,42 @@ class LocationContext : public llvm::FoldingSetNode {
|
||||
const ImplicitParamDecl *getSelfDecl() const {
|
||||
return Ctx->getSelfDecl();
|
||||
}
|
||||
|
||||
const StackFrameContext *getCurrentStackFrame() const;
|
||||
const StackFrameContext *
|
||||
getStackFrameForDeclContext(const DeclContext *DC) const;
|
||||
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, Kind, Ctx, Parent);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, ContextKind k,
|
||||
AnalysisContext *ctx, const LocationContext *parent);
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
|
||||
|
||||
static bool classof(const LocationContext*) { return true; }
|
||||
|
||||
public:
|
||||
static void ProfileCommon(llvm::FoldingSetNodeID &ID,
|
||||
ContextKind ck,
|
||||
AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const void* data);
|
||||
};
|
||||
|
||||
class StackFrameContext : public LocationContext {
|
||||
const Stmt *CallSite;
|
||||
|
||||
public:
|
||||
friend class LocationContextManager;
|
||||
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s)
|
||||
: LocationContext(StackFrame, ctx, parent), CallSite(s) {}
|
||||
|
||||
public:
|
||||
~StackFrameContext() {}
|
||||
|
||||
const Stmt *getCallSite() const { return CallSite; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
virtual ~StackFrameContext() {}
|
||||
|
||||
|
||||
Stmt const *getCallSite() const { return CallSite; }
|
||||
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getAnalysisContext(), getParent(), CallSite);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const Stmt *s);
|
||||
const LocationContext *parent, const Stmt *s) {
|
||||
ProfileCommon(ID, StackFrame, ctx, parent, s);
|
||||
}
|
||||
|
||||
static bool classof(const LocationContext* Ctx) {
|
||||
return Ctx->getKind() == StackFrame;
|
||||
@ -152,41 +162,91 @@ class StackFrameContext : public LocationContext {
|
||||
|
||||
class ScopeContext : public LocationContext {
|
||||
const Stmt *Enter;
|
||||
|
||||
public:
|
||||
|
||||
friend class LocationContextManager;
|
||||
ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s)
|
||||
: LocationContext(Scope, ctx, parent), Enter(s) {}
|
||||
|
||||
virtual ~ScopeContext() {}
|
||||
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getAnalysisContext(), getParent(), Enter);
|
||||
}
|
||||
public:
|
||||
~ScopeContext() {}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const Stmt *s);
|
||||
const LocationContext *parent, const Stmt *s) {
|
||||
ProfileCommon(ID, Scope, ctx, parent, s);
|
||||
}
|
||||
|
||||
static bool classof(const LocationContext* Ctx) {
|
||||
return Ctx->getKind() == Scope;
|
||||
}
|
||||
};
|
||||
|
||||
class BlockInvocationContext : public LocationContext {
|
||||
llvm::PointerUnion<const BlockDataRegion *, const BlockDecl *> Data;
|
||||
|
||||
friend class LocationContextManager;
|
||||
|
||||
BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const BlockDataRegion *br)
|
||||
: LocationContext(Block, ctx, parent), Data(br) {}
|
||||
|
||||
BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const BlockDecl *bd)
|
||||
: LocationContext(Block, ctx, parent), Data(bd) {}
|
||||
|
||||
public:
|
||||
~BlockInvocationContext() {}
|
||||
|
||||
const BlockDataRegion *getBlockRegion() const {
|
||||
return Data.is<const BlockDataRegion*>() ?
|
||||
Data.get<const BlockDataRegion*>() : 0;
|
||||
}
|
||||
|
||||
const BlockDecl *getBlockDecl() const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const BlockDataRegion *br){
|
||||
ProfileCommon(ID, Block, ctx, parent, br);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const BlockDecl *bd) {
|
||||
ProfileCommon(ID, Block, ctx, parent, bd);
|
||||
}
|
||||
|
||||
static bool classof(const LocationContext* Ctx) {
|
||||
return Ctx->getKind() == Block;
|
||||
}
|
||||
};
|
||||
|
||||
class LocationContextManager {
|
||||
llvm::FoldingSet<LocationContext> Contexts;
|
||||
|
||||
public:
|
||||
~LocationContextManager();
|
||||
|
||||
StackFrameContext *getStackFrame(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
|
||||
ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
const ScopeContext *getScope(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
|
||||
const BlockInvocationContext *
|
||||
getBlockInvocation(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const BlockDataRegion *BR);
|
||||
|
||||
/// Discard all previously created LocationContext objects.
|
||||
void clear();
|
||||
private:
|
||||
template <typename LOC, typename DATA>
|
||||
const LOC *getLocationContext(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const DATA *d);
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
@ -56,8 +56,7 @@ class AnalysisManager : public BugReporterData {
|
||||
const LangOptions &lang, PathDiagnosticClient *pd,
|
||||
StoreManagerCreator storemgr,
|
||||
ConstraintManagerCreator constraintmgr,
|
||||
bool displayProgress, bool vizdot, bool vizubi,
|
||||
bool purge, bool eager, bool trim)
|
||||
bool vizdot, bool vizubi, bool purge, bool eager, bool trim)
|
||||
|
||||
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
|
||||
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
|
||||
@ -132,7 +131,7 @@ class AnalysisManager : public BugReporterData {
|
||||
}
|
||||
|
||||
// Get the top level stack frame.
|
||||
StackFrameContext *getStackFrame(Decl const *D) {
|
||||
const StackFrameContext *getStackFrame(Decl const *D) {
|
||||
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
|
||||
#define LLVM_CLANG_ANALYSIS_BUGTYPE
|
||||
|
||||
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
||||
#include <llvm/ADT/FoldingSet.h>
|
||||
#include <string>
|
||||
|
||||
|
@ -39,7 +39,7 @@ class CheckerContext {
|
||||
SaveAndRestore<const void*> OldTag;
|
||||
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
|
||||
SaveOr OldHasGen;
|
||||
const GRState *state;
|
||||
const GRState *ST;
|
||||
const Stmt *statement;
|
||||
const unsigned size;
|
||||
bool DoneEvaluating; // FIXME: This is not a permanent API change.
|
||||
@ -53,22 +53,14 @@ class CheckerContext {
|
||||
OldTag(B.Tag, tag),
|
||||
OldPointKind(B.PointKind, K),
|
||||
OldHasGen(B.HasGeneratedNode),
|
||||
state(st), statement(stmt), size(Dst.size()),
|
||||
DoneEvaluating(false) {}
|
||||
ST(st), statement(stmt), size(Dst.size()) {}
|
||||
|
||||
~CheckerContext();
|
||||
|
||||
// FIXME: This were added to support CallAndMessageChecker to indicating
|
||||
// to GRExprEngine to "stop evaluating" a message expression under certain
|
||||
// cases. This is *not* meant to be a permanent API change, and was added
|
||||
// to aid in the transition of removing logic for checks from GRExprEngine.
|
||||
void setDoneEvaluating() {
|
||||
DoneEvaluating = true;
|
||||
|
||||
GRExprEngine &getEngine() {
|
||||
return Eng;
|
||||
}
|
||||
bool isDoneEvaluating() const {
|
||||
return DoneEvaluating;
|
||||
}
|
||||
|
||||
|
||||
ConstraintManager &getConstraintManager() {
|
||||
return Eng.getConstraintManager();
|
||||
}
|
||||
@ -80,7 +72,7 @@ class CheckerContext {
|
||||
ExplodedNodeSet &getNodeSet() { return Dst; }
|
||||
GRStmtNodeBuilder &getNodeBuilder() { return B; }
|
||||
ExplodedNode *&getPredecessor() { return Pred; }
|
||||
const GRState *getState() { return state ? state : B.GetState(Pred); }
|
||||
const GRState *getState() { return ST ? ST : B.GetState(Pred); }
|
||||
|
||||
ASTContext &getASTContext() {
|
||||
return Eng.getContext();
|
||||
@ -98,6 +90,10 @@ class CheckerContext {
|
||||
return Eng.getValueManager();
|
||||
}
|
||||
|
||||
SValuator &getSValuator() {
|
||||
return Eng.getSValuator();
|
||||
}
|
||||
|
||||
ExplodedNode *GenerateNode(bool autoTransition = true) {
|
||||
assert(statement && "Only transitions with statements currently supported");
|
||||
ExplodedNode *N = GenerateNodeImpl(statement, getState(), false);
|
||||
@ -115,6 +111,15 @@ class CheckerContext {
|
||||
return N;
|
||||
}
|
||||
|
||||
ExplodedNode *GenerateNode(const GRState *state, ExplodedNode *pred,
|
||||
bool autoTransition = true) {
|
||||
assert(statement && "Only transitions with statements currently supported");
|
||||
ExplodedNode *N = GenerateNodeImpl(statement, state, pred, false);
|
||||
if (N && autoTransition)
|
||||
addTransition(N);
|
||||
return N;
|
||||
}
|
||||
|
||||
ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) {
|
||||
assert(statement && "Only transitions with statements currently supported");
|
||||
ExplodedNode *N = GenerateNodeImpl(statement, state, false);
|
||||
@ -138,8 +143,7 @@ class CheckerContext {
|
||||
|
||||
void addTransition(const GRState *state) {
|
||||
assert(state);
|
||||
if (state != getState() ||
|
||||
(state && state != B.GetState(Pred)))
|
||||
if (state != getState() || (ST && ST != B.GetState(Pred)))
|
||||
GenerateNode(state, true);
|
||||
else
|
||||
Dst.Add(Pred);
|
||||
@ -157,7 +161,14 @@ class CheckerContext {
|
||||
node->markAsSink();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
|
||||
ExplodedNode *pred, bool markAsSink) {
|
||||
ExplodedNode *node = B.generateNode(stmt, state, pred);
|
||||
if (markAsSink && node)
|
||||
node->markAsSink();
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
class Checker {
|
||||
@ -165,7 +176,7 @@ class Checker {
|
||||
friend class GRExprEngine;
|
||||
|
||||
// FIXME: Remove the 'tag' option.
|
||||
bool GR_Visit(ExplodedNodeSet &Dst,
|
||||
void GR_Visit(ExplodedNodeSet &Dst,
|
||||
GRStmtNodeBuilder &Builder,
|
||||
GRExprEngine &Eng,
|
||||
const Stmt *S,
|
||||
@ -177,7 +188,22 @@ class Checker {
|
||||
_PreVisit(C, S);
|
||||
else
|
||||
_PostVisit(C, S);
|
||||
return C.isDoneEvaluating();
|
||||
}
|
||||
|
||||
bool GR_EvalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
||||
GRExprEngine &Eng, const ObjCMessageExpr *ME,
|
||||
ExplodedNode *Pred, const GRState *state, void *tag) {
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
|
||||
ME, state);
|
||||
return EvalNilReceiver(C, ME);
|
||||
}
|
||||
|
||||
bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
|
||||
GRExprEngine &Eng, const CallExpr *CE,
|
||||
ExplodedNode *Pred, void *tag) {
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
|
||||
CE);
|
||||
return EvalCallExpr(C, CE);
|
||||
}
|
||||
|
||||
// FIXME: Remove the 'tag' option.
|
||||
@ -231,6 +257,14 @@ class Checker {
|
||||
virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
|
||||
GRExprEngine &Eng,
|
||||
Stmt *Condition, void *tag) {}
|
||||
|
||||
virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // end clang namespace
|
||||
|
||||
|
@ -209,8 +209,17 @@ class GRExprEngine : public GRSubEngine {
|
||||
protected:
|
||||
/// CheckerVisit - Dispatcher for performing checker-specific logic
|
||||
/// at specific statements.
|
||||
bool CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
||||
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
||||
bool isPrevisit);
|
||||
|
||||
bool CheckerEvalCall(const CallExpr *CE,
|
||||
ExplodedNodeSet &Dst,
|
||||
ExplodedNode *Pred);
|
||||
|
||||
void CheckerEvalNilReceiver(const ObjCMessageExpr *ME,
|
||||
ExplodedNodeSet &Dst,
|
||||
const GRState *state,
|
||||
ExplodedNode *Pred);
|
||||
|
||||
void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
|
||||
ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
||||
@ -272,6 +281,13 @@ class GRExprEngine : public GRSubEngine {
|
||||
void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred,
|
||||
ExplodedNodeSet& Dst, bool asLValue);
|
||||
|
||||
/// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
|
||||
void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred,
|
||||
ExplodedNodeSet& Dst, bool asLValue);
|
||||
|
||||
void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred,
|
||||
ExplodedNodeSet& Dst, bool asLValue);
|
||||
|
||||
/// VisitDeclStmt - Transfer function logic for DeclStmts.
|
||||
void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
||||
|
||||
@ -358,9 +374,10 @@ class GRExprEngine : public GRSubEngine {
|
||||
}
|
||||
|
||||
protected:
|
||||
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) {
|
||||
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME,
|
||||
ExplodedNode* Pred, const GRState *state) {
|
||||
assert (Builder && "GRStmtNodeBuilder must be defined.");
|
||||
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
|
||||
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
|
||||
}
|
||||
|
||||
const GRState* MarkBranch(const GRState* St, Stmt* Terminator,
|
||||
|
@ -217,6 +217,7 @@ class GRState : public llvm::FoldingSetNode {
|
||||
/// for the compound literal and 'BegInit' and 'EndInit' represent an
|
||||
/// array of initializer values.
|
||||
const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
const LocationContext *LC,
|
||||
SVal V) const;
|
||||
|
||||
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
|
||||
@ -237,7 +238,8 @@ class GRState : public llvm::FoldingSetNode {
|
||||
/// Get the lvalue for a StringLiteral.
|
||||
SVal getLValue(const StringLiteral *literal) const;
|
||||
|
||||
SVal getLValue(const CompoundLiteralExpr *literal) const;
|
||||
SVal getLValue(const CompoundLiteralExpr *literal,
|
||||
const LocationContext *LC) const;
|
||||
|
||||
/// Get the lvalue for an ivar reference.
|
||||
SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
|
||||
@ -609,9 +611,10 @@ inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
|
||||
cast<DefinedSVal>(UpperBound), Assumption);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
SVal V) const {
|
||||
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V);
|
||||
inline const GRState *
|
||||
GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
const LocationContext *LC, SVal V) const {
|
||||
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, LC, V);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
|
||||
@ -639,8 +642,9 @@ inline SVal GRState::getLValue(const StringLiteral *literal) const {
|
||||
return getStateManager().StoreMgr->getLValueString(literal);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(const CompoundLiteralExpr *literal) const {
|
||||
return getStateManager().StoreMgr->getLValueCompoundLiteral(literal);
|
||||
inline SVal GRState::getLValue(const CompoundLiteralExpr *literal,
|
||||
const LocationContext *LC) const {
|
||||
return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
|
||||
|
@ -47,7 +47,8 @@ class GRTransferFuncs {
|
||||
GRExprEngine& Engine,
|
||||
GRStmtNodeBuilder& Builder,
|
||||
ObjCMessageExpr* ME,
|
||||
ExplodedNode* Pred) {}
|
||||
ExplodedNode* Pred,
|
||||
const GRState *state) {}
|
||||
|
||||
// Stores.
|
||||
|
||||
|
@ -35,6 +35,7 @@ namespace clang {
|
||||
class MemRegionManager;
|
||||
class MemSpaceRegion;
|
||||
class LocationContext;
|
||||
class StackFrameContext;
|
||||
class VarRegion;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -45,22 +46,37 @@ class VarRegion;
|
||||
class MemRegion : public llvm::FoldingSetNode {
|
||||
friend class MemRegionManager;
|
||||
public:
|
||||
enum Kind { MemSpaceRegionKind,
|
||||
SymbolicRegionKind,
|
||||
AllocaRegionKind,
|
||||
// Typed regions.
|
||||
BEG_TYPED_REGIONS,
|
||||
FunctionTextRegionKind,
|
||||
BlockTextRegionKind,
|
||||
BlockDataRegionKind,
|
||||
CompoundLiteralRegionKind,
|
||||
StringRegionKind, ElementRegionKind,
|
||||
// Decl Regions.
|
||||
BEG_DECL_REGIONS,
|
||||
VarRegionKind, FieldRegionKind,
|
||||
ObjCIvarRegionKind, ObjCObjectRegionKind,
|
||||
END_DECL_REGIONS,
|
||||
END_TYPED_REGIONS };
|
||||
enum Kind {
|
||||
// Memory spaces.
|
||||
BEG_MEMSPACES,
|
||||
GenericMemSpaceRegionKind = BEG_MEMSPACES,
|
||||
StackLocalsSpaceRegionKind,
|
||||
StackArgumentsSpaceRegionKind,
|
||||
HeapSpaceRegionKind,
|
||||
UnknownSpaceRegionKind,
|
||||
GlobalsSpaceRegionKind,
|
||||
END_MEMSPACES = GlobalsSpaceRegionKind,
|
||||
// Untyped regions.
|
||||
SymbolicRegionKind,
|
||||
AllocaRegionKind,
|
||||
// Typed regions.
|
||||
BEG_TYPED_REGIONS,
|
||||
FunctionTextRegionKind = BEG_TYPED_REGIONS,
|
||||
BlockTextRegionKind,
|
||||
BlockDataRegionKind,
|
||||
CompoundLiteralRegionKind,
|
||||
StringRegionKind,
|
||||
ElementRegionKind,
|
||||
// Decl Regions.
|
||||
BEG_DECL_REGIONS,
|
||||
VarRegionKind = BEG_DECL_REGIONS,
|
||||
FieldRegionKind,
|
||||
ObjCIvarRegionKind,
|
||||
ObjCObjectRegionKind,
|
||||
END_DECL_REGIONS = ObjCObjectRegionKind,
|
||||
END_TYPED_REGIONS = END_DECL_REGIONS
|
||||
};
|
||||
|
||||
private:
|
||||
const Kind kind;
|
||||
|
||||
@ -111,25 +127,102 @@ class MemRegion : public llvm::FoldingSetNode {
|
||||
/// MemSpaceRegion - A memory region that represents and "memory space";
|
||||
/// for example, the set of global variables, the stack frame, etc.
|
||||
class MemSpaceRegion : public MemRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
protected:
|
||||
friend class MemRegionManager;
|
||||
|
||||
MemRegionManager *Mgr;
|
||||
|
||||
MemSpaceRegion(MemRegionManager *mgr) : MemRegion(MemSpaceRegionKind),
|
||||
Mgr(mgr) {}
|
||||
|
||||
MemRegionManager* getMemRegionManager() const {
|
||||
return Mgr;
|
||||
MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind)
|
||||
: MemRegion(k), Mgr(mgr) {
|
||||
assert(classof(this));
|
||||
}
|
||||
|
||||
MemRegionManager* getMemRegionManager() const { return Mgr; }
|
||||
|
||||
public:
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const;
|
||||
|
||||
bool isBoundable() const { return false; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() == MemSpaceRegionKind;
|
||||
static bool classof(const MemRegion *R) {
|
||||
Kind k = R->getKind();
|
||||
return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalsSpaceRegion : public MemSpaceRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
GlobalsSpaceRegion(MemRegionManager *mgr)
|
||||
: MemSpaceRegion(mgr, GlobalsSpaceRegionKind) {}
|
||||
public:
|
||||
static bool classof(const MemRegion *R) {
|
||||
return R->getKind() == GlobalsSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
class HeapSpaceRegion : public MemSpaceRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
HeapSpaceRegion(MemRegionManager *mgr)
|
||||
: MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
|
||||
public:
|
||||
static bool classof(const MemRegion *R) {
|
||||
return R->getKind() == HeapSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
class UnknownSpaceRegion : public MemSpaceRegion {
|
||||
friend class MemRegionManager;
|
||||
UnknownSpaceRegion(MemRegionManager *mgr)
|
||||
: MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
|
||||
public:
|
||||
static bool classof(const MemRegion *R) {
|
||||
return R->getKind() == UnknownSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
class StackSpaceRegion : public MemSpaceRegion {
|
||||
private:
|
||||
const StackFrameContext *SFC;
|
||||
|
||||
protected:
|
||||
StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
|
||||
: MemSpaceRegion(mgr, k), SFC(sfc) {
|
||||
assert(classof(this));
|
||||
}
|
||||
|
||||
public:
|
||||
const StackFrameContext *getStackFrame() const { return SFC; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
static bool classof(const MemRegion *R) {
|
||||
Kind k = R->getKind();
|
||||
return k >= StackLocalsSpaceRegionKind &&
|
||||
k <= StackArgumentsSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
class StackLocalsSpaceRegion : public StackSpaceRegion {
|
||||
private:
|
||||
friend class MemRegionManager;
|
||||
StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
|
||||
: StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
|
||||
public:
|
||||
static bool classof(const MemRegion *R) {
|
||||
return R->getKind() == StackLocalsSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
class StackArgumentsSpaceRegion : public StackSpaceRegion {
|
||||
private:
|
||||
friend class MemRegionManager;
|
||||
StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
|
||||
: StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
|
||||
public:
|
||||
static bool classof(const MemRegion *R) {
|
||||
return R->getKind() == StackArgumentsSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -149,7 +242,7 @@ class SubRegion : public MemRegion {
|
||||
bool isSubRegionOf(const MemRegion* R) const;
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() > MemSpaceRegionKind;
|
||||
return R->getKind() > END_MEMSPACES;
|
||||
}
|
||||
};
|
||||
|
||||
@ -237,7 +330,7 @@ class TypedRegion : public SubRegion {
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
unsigned k = R->getKind();
|
||||
return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
|
||||
return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
|
||||
}
|
||||
};
|
||||
|
||||
@ -295,12 +388,17 @@ class FunctionTextRegion : public CodeTextRegion {
|
||||
/// like a closure a block captures the values of externally referenced
|
||||
/// variables.
|
||||
class BlockTextRegion : public CodeTextRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
const BlockDecl *BD;
|
||||
AnalysisContext *AC;
|
||||
CanQualType locTy;
|
||||
public:
|
||||
BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg)
|
||||
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {}
|
||||
|
||||
|
||||
BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
|
||||
AnalysisContext *ac, const MemRegion* sreg)
|
||||
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
|
||||
|
||||
public:
|
||||
QualType getLocationType(ASTContext &C) const {
|
||||
return locTy;
|
||||
}
|
||||
@ -308,13 +406,16 @@ class BlockTextRegion : public CodeTextRegion {
|
||||
const BlockDecl *getDecl() const {
|
||||
return BD;
|
||||
}
|
||||
|
||||
AnalysisContext *getAnalysisContext() const { return AC; }
|
||||
|
||||
virtual void dumpToStream(llvm::raw_ostream& os) const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const;
|
||||
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
|
||||
CanQualType, const MemRegion*);
|
||||
CanQualType, const AnalysisContext*,
|
||||
const MemRegion*);
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() == BlockTextRegionKind;
|
||||
@ -329,18 +430,45 @@ class BlockTextRegion : public CodeTextRegion {
|
||||
/// variables.
|
||||
/// BlockDataRegion - A region that represents code texts of blocks (closures).
|
||||
class BlockDataRegion : public SubRegion {
|
||||
friend class MemRegionManager;
|
||||
const BlockTextRegion *BC;
|
||||
const LocationContext *LC;
|
||||
const LocationContext *LC; // Can be null */
|
||||
void *ReferencedVars;
|
||||
public:
|
||||
BlockDataRegion(const BlockTextRegion *bc,
|
||||
const LocationContext *lc,
|
||||
|
||||
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
|
||||
const MemRegion *sreg)
|
||||
: SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
|
||||
|
||||
public:
|
||||
const BlockTextRegion *getCodeRegion() const { return BC; }
|
||||
|
||||
typedef const MemRegion * const * referenced_vars_iterator;
|
||||
const BlockDecl *getDecl() const { return BC->getDecl(); }
|
||||
|
||||
class referenced_vars_iterator {
|
||||
const MemRegion * const *R;
|
||||
public:
|
||||
explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {}
|
||||
|
||||
operator const MemRegion * const *() const {
|
||||
return R;
|
||||
}
|
||||
|
||||
const VarRegion* operator*() const {
|
||||
return cast<VarRegion>(*R);
|
||||
}
|
||||
|
||||
bool operator==(const referenced_vars_iterator &I) const {
|
||||
return I.R == R;
|
||||
}
|
||||
bool operator!=(const referenced_vars_iterator &I) const {
|
||||
return I.R != R;
|
||||
}
|
||||
referenced_vars_iterator& operator++() {
|
||||
++R;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
referenced_vars_iterator referenced_vars_begin() const;
|
||||
referenced_vars_iterator referenced_vars_end() const;
|
||||
|
||||
@ -348,9 +476,8 @@ class BlockDataRegion : public SubRegion {
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const;
|
||||
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
|
||||
const BlockTextRegion *BC,
|
||||
const LocationContext *LC, const MemRegion *);
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
|
||||
const LocationContext *, const MemRegion *);
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() == BlockDataRegionKind;
|
||||
@ -473,25 +600,20 @@ class DeclRegion : public TypedRegion {
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
unsigned k = R->getKind();
|
||||
return k > BEG_DECL_REGIONS && k < END_DECL_REGIONS;
|
||||
return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
|
||||
}
|
||||
};
|
||||
|
||||
class VarRegion : public DeclRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
// Data.
|
||||
const LocationContext *LC;
|
||||
|
||||
// Constructors and private methods.
|
||||
VarRegion(const VarDecl* vd, const LocationContext *lC, const MemRegion* sReg)
|
||||
: DeclRegion(vd, sReg, VarRegionKind), LC(lC) {}
|
||||
VarRegion(const VarDecl* vd, const MemRegion* sReg)
|
||||
: DeclRegion(vd, sReg, VarRegionKind) {}
|
||||
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD,
|
||||
const LocationContext *LC,
|
||||
const MemRegion *superRegion) {
|
||||
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
|
||||
ID.AddPointer(LC);
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const;
|
||||
@ -499,8 +621,8 @@ class VarRegion : public DeclRegion {
|
||||
public:
|
||||
const VarDecl *getDecl() const { return cast<VarDecl>(D); }
|
||||
|
||||
const LocationContext *getLocationContext() const { return LC; }
|
||||
|
||||
const StackFrameContext *getStackFrame() const;
|
||||
|
||||
QualType getValueType(ASTContext& C) const {
|
||||
// FIXME: We can cache this if needed.
|
||||
return C.getCanonicalType(getDecl()->getType());
|
||||
@ -647,17 +769,24 @@ class MemRegionManager {
|
||||
llvm::BumpPtrAllocator& A;
|
||||
llvm::FoldingSet<MemRegion> Regions;
|
||||
|
||||
MemSpaceRegion *globals;
|
||||
MemSpaceRegion *stack;
|
||||
MemSpaceRegion *stackArguments;
|
||||
MemSpaceRegion *heap;
|
||||
MemSpaceRegion *unknown;
|
||||
GlobalsSpaceRegion *globals;
|
||||
|
||||
const StackFrameContext *cachedStackLocalsFrame;
|
||||
StackLocalsSpaceRegion *cachedStackLocalsRegion;
|
||||
|
||||
const StackFrameContext *cachedStackArgumentsFrame;
|
||||
StackArgumentsSpaceRegion *cachedStackArgumentsRegion;
|
||||
|
||||
HeapSpaceRegion *heap;
|
||||
UnknownSpaceRegion *unknown;
|
||||
MemSpaceRegion *code;
|
||||
|
||||
public:
|
||||
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
|
||||
: C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0),
|
||||
unknown(0), code(0) {}
|
||||
: C(c), A(a), globals(0),
|
||||
cachedStackLocalsFrame(0), cachedStackLocalsRegion(0),
|
||||
cachedStackArgumentsFrame(0), cachedStackArgumentsRegion(0),
|
||||
heap(0), unknown(0), code(0) {}
|
||||
|
||||
~MemRegionManager();
|
||||
|
||||
@ -665,52 +794,60 @@ class MemRegionManager {
|
||||
|
||||
llvm::BumpPtrAllocator &getAllocator() { return A; }
|
||||
|
||||
/// getStackRegion - Retrieve the memory region associated with the
|
||||
/// current stack frame.
|
||||
MemSpaceRegion *getStackRegion();
|
||||
/// getStackLocalsRegion - Retrieve the memory region associated with the
|
||||
/// specified stack frame.
|
||||
const StackLocalsSpaceRegion *
|
||||
getStackLocalsRegion(const StackFrameContext *STC);
|
||||
|
||||
/// getStackArgumentsRegion - Retrieve the memory region associated with
|
||||
/// function/method arguments of the current stack frame.
|
||||
MemSpaceRegion *getStackArgumentsRegion();
|
||||
/// function/method arguments of the specified stack frame.
|
||||
const StackArgumentsSpaceRegion *
|
||||
getStackArgumentsRegion(const StackFrameContext *STC);
|
||||
|
||||
/// getGlobalsRegion - Retrieve the memory region associated with
|
||||
/// all global variables.
|
||||
MemSpaceRegion *getGlobalsRegion();
|
||||
const GlobalsSpaceRegion *getGlobalsRegion();
|
||||
|
||||
/// getHeapRegion - Retrieve the memory region associated with the
|
||||
/// generic "heap".
|
||||
MemSpaceRegion *getHeapRegion();
|
||||
const HeapSpaceRegion *getHeapRegion();
|
||||
|
||||
/// getUnknownRegion - Retrieve the memory region associated with unknown
|
||||
/// memory space.
|
||||
MemSpaceRegion *getUnknownRegion();
|
||||
const MemSpaceRegion *getUnknownRegion();
|
||||
|
||||
MemSpaceRegion *getCodeRegion();
|
||||
const MemSpaceRegion *getCodeRegion();
|
||||
|
||||
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
|
||||
AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt);
|
||||
const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt,
|
||||
const LocationContext *LC);
|
||||
|
||||
/// getCompoundLiteralRegion - Retrieve the region associated with a
|
||||
/// given CompoundLiteral.
|
||||
CompoundLiteralRegion*
|
||||
getCompoundLiteralRegion(const CompoundLiteralExpr* CL);
|
||||
const CompoundLiteralRegion*
|
||||
getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
|
||||
const LocationContext *LC);
|
||||
|
||||
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
|
||||
SymbolicRegion* getSymbolicRegion(SymbolRef sym);
|
||||
const SymbolicRegion* getSymbolicRegion(SymbolRef sym);
|
||||
|
||||
StringRegion* getStringRegion(const StringLiteral* Str);
|
||||
const StringRegion* getStringRegion(const StringLiteral* Str);
|
||||
|
||||
/// getVarRegion - Retrieve or create the memory region associated with
|
||||
/// a specified VarDecl and LocationContext.
|
||||
VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
|
||||
const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
|
||||
|
||||
/// getVarRegion - Retrieve or create the memory region associated with
|
||||
/// a specified VarDecl and super region.
|
||||
const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR);
|
||||
|
||||
/// getElementRegion - Retrieve the memory region associated with the
|
||||
/// associated element type, index, and super region.
|
||||
ElementRegion *getElementRegion(QualType elementType, SVal Idx,
|
||||
const ElementRegion *getElementRegion(QualType elementType, SVal Idx,
|
||||
const MemRegion *superRegion,
|
||||
ASTContext &Ctx);
|
||||
|
||||
ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
|
||||
const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
|
||||
const MemRegion *superRegion) {
|
||||
return getElementRegion(ER->getElementType(), ER->getIndex(),
|
||||
superRegion, ER->getContext());
|
||||
@ -720,31 +857,44 @@ class MemRegionManager {
|
||||
/// a specified FieldDecl. 'superRegion' corresponds to the containing
|
||||
/// memory region (which typically represents the memory representing
|
||||
/// a structure or class).
|
||||
FieldRegion *getFieldRegion(const FieldDecl* fd,
|
||||
const MemRegion* superRegion);
|
||||
const FieldRegion *getFieldRegion(const FieldDecl* fd,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
|
||||
const MemRegion *superRegion) {
|
||||
const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
|
||||
const MemRegion *superRegion) {
|
||||
return getFieldRegion(FR->getDecl(), superRegion);
|
||||
}
|
||||
|
||||
/// getObjCObjectRegion - Retrieve or create the memory region associated with
|
||||
/// the instance of a specified Objective-C class.
|
||||
ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID,
|
||||
const MemRegion* superRegion);
|
||||
const ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
/// getObjCIvarRegion - Retrieve or create the memory region associated with
|
||||
/// a specified Objective-c instance variable. 'superRegion' corresponds
|
||||
/// to the containing region (which typically represents the Objective-C
|
||||
/// object).
|
||||
ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
|
||||
const MemRegion* superRegion);
|
||||
const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
|
||||
BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy);
|
||||
BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
|
||||
const LocationContext *lc);
|
||||
const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
|
||||
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
|
||||
CanQualType locTy,
|
||||
AnalysisContext *AC);
|
||||
|
||||
/// getBlockDataRegion - Get the memory region associated with an instance
|
||||
/// of a block. Unlike many other MemRegions, the LocationContext*
|
||||
/// argument is allowed to be NULL for cases where we have no known
|
||||
/// context.
|
||||
const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
|
||||
const LocationContext *lc = NULL);
|
||||
|
||||
bool isGlobalsRegion(const MemRegion* R) {
|
||||
assert(R);
|
||||
return R == globals;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename RegionTy, typename A1>
|
||||
RegionTy* getRegion(const A1 a1);
|
||||
|
||||
@ -758,13 +908,15 @@ class MemRegionManager {
|
||||
RegionTy* getSubRegion(const A1 a1, const A2 a2,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
bool isGlobalsRegion(const MemRegion* R) {
|
||||
assert(R);
|
||||
return R == globals;
|
||||
}
|
||||
|
||||
private:
|
||||
MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
|
||||
template <typename RegionTy, typename A1, typename A2, typename A3>
|
||||
RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
template <typename REG>
|
||||
const REG* LazyAllocate(REG*& region);
|
||||
|
||||
template <typename REG, typename ARG>
|
||||
const REG* LazyAllocate(REG*& region, ARG a);
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -774,157 +926,6 @@ class MemRegionManager {
|
||||
inline ASTContext& MemRegion::getContext() const {
|
||||
return getMemRegionManager()->getContext();
|
||||
}
|
||||
|
||||
template<typename RegionTy> struct MemRegionManagerTrait;
|
||||
|
||||
template <typename RegionTy, typename A1>
|
||||
RegionTy* MemRegionManager::getRegion(const A1 a1) {
|
||||
|
||||
const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
|
||||
MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1);
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
RegionTy::ProfileRegion(ID, a1, superRegion);
|
||||
void* InsertPos;
|
||||
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
|
||||
InsertPos));
|
||||
|
||||
if (!R) {
|
||||
R = (RegionTy*) A.Allocate<RegionTy>();
|
||||
new (R) RegionTy(a1, superRegion);
|
||||
Regions.InsertNode(R, InsertPos);
|
||||
}
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
template <typename RegionTy, typename A1>
|
||||
RegionTy* MemRegionManager::getSubRegion(const A1 a1,
|
||||
const MemRegion *superRegion) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
RegionTy::ProfileRegion(ID, a1, superRegion);
|
||||
void* InsertPos;
|
||||
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
|
||||
InsertPos));
|
||||
|
||||
if (!R) {
|
||||
R = (RegionTy*) A.Allocate<RegionTy>();
|
||||
new (R) RegionTy(a1, superRegion);
|
||||
Regions.InsertNode(R, InsertPos);
|
||||
}
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
template <typename RegionTy, typename A1, typename A2>
|
||||
RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
|
||||
|
||||
const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
|
||||
MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2);
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
RegionTy::ProfileRegion(ID, a1, a2, superRegion);
|
||||
void* InsertPos;
|
||||
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
|
||||
InsertPos));
|
||||
|
||||
if (!R) {
|
||||
R = (RegionTy*) A.Allocate<RegionTy>();
|
||||
new (R) RegionTy(a1, a2, superRegion);
|
||||
Regions.InsertNode(R, InsertPos);
|
||||
}
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
template <typename RegionTy, typename A1, typename A2>
|
||||
RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
|
||||
const MemRegion *superRegion) {
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
RegionTy::ProfileRegion(ID, a1, a2, superRegion);
|
||||
void* InsertPos;
|
||||
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
|
||||
InsertPos));
|
||||
|
||||
if (!R) {
|
||||
R = (RegionTy*) A.Allocate<RegionTy>();
|
||||
new (R) RegionTy(a1, a2, superRegion);
|
||||
Regions.InsertNode(R, InsertPos);
|
||||
}
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Traits for constructing regions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template <> struct MemRegionManagerTrait<AllocaRegion> {
|
||||
typedef MemRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
|
||||
const Expr *, unsigned) {
|
||||
return MRMgr.getStackRegion();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MemRegionManagerTrait<CompoundLiteralRegion> {
|
||||
typedef MemRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
|
||||
const CompoundLiteralExpr *CL) {
|
||||
|
||||
return CL->isFileScope() ? MRMgr.getGlobalsRegion()
|
||||
: MRMgr.getStackRegion();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MemRegionManagerTrait<StringRegion> {
|
||||
typedef MemSpaceRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
|
||||
const StringLiteral*) {
|
||||
return MRMgr.getGlobalsRegion();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MemRegionManagerTrait<VarRegion> {
|
||||
typedef MemRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager &MRMgr,
|
||||
const VarDecl *D,
|
||||
const LocationContext *LC) {
|
||||
|
||||
// FIXME: Make stack regions have a location context?
|
||||
|
||||
if (D->hasLocalStorage()) {
|
||||
return isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
|
||||
? MRMgr.getStackArgumentsRegion() : MRMgr.getStackRegion();
|
||||
}
|
||||
|
||||
return MRMgr.getGlobalsRegion();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MemRegionManagerTrait<SymbolicRegion> {
|
||||
typedef MemRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
|
||||
SymbolRef) {
|
||||
return MRMgr.getUnknownRegion();
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct MemRegionManagerTrait<FunctionTextRegion> {
|
||||
typedef MemSpaceRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
|
||||
const FunctionDecl*) {
|
||||
return MRMgr.getCodeRegion();
|
||||
}
|
||||
};
|
||||
template<> struct MemRegionManagerTrait<BlockTextRegion> {
|
||||
typedef MemSpaceRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
|
||||
const BlockDecl*, CanQualType) {
|
||||
return MRMgr.getCodeRegion();
|
||||
}
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
|
@ -73,8 +73,9 @@ class StoreManager {
|
||||
/// for the compound literal and 'BegInit' and 'EndInit' represent an
|
||||
/// array of initializer values.
|
||||
virtual const GRState *BindCompoundLiteral(const GRState *state,
|
||||
const CompoundLiteralExpr* cl,
|
||||
SVal v) = 0;
|
||||
const CompoundLiteralExpr* cl,
|
||||
const LocationContext *LC,
|
||||
SVal v) = 0;
|
||||
|
||||
/// getInitialStore - Returns the initial "empty" store representing the
|
||||
/// value bindings upon entry to an analyzed function.
|
||||
@ -93,7 +94,8 @@ class StoreManager {
|
||||
|
||||
virtual SVal getLValueString(const StringLiteral* sl) = 0;
|
||||
|
||||
virtual SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl) = 0;
|
||||
SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl,
|
||||
const LocationContext *LC);
|
||||
|
||||
virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) = 0;
|
||||
|
||||
@ -147,6 +149,12 @@ class StoreManager {
|
||||
const MemRegion *R,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS) = 0;
|
||||
|
||||
virtual const GRState *InvalidateRegions(const GRState *state,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS);
|
||||
|
||||
// FIXME: Make out-of-line.
|
||||
virtual const GRState *setExtent(const GRState *state,
|
||||
|
@ -28,10 +28,12 @@ namespace llvm {
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class MemRegion;
|
||||
class TypedRegion;
|
||||
class ASTContext;
|
||||
class BasicValueFactory;
|
||||
class MemRegion;
|
||||
class TypedRegion;
|
||||
class VarRegion;
|
||||
class StackFrameContext;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
@ -332,10 +334,13 @@ class SymbolReaper {
|
||||
SetTy TheDead;
|
||||
LiveVariables& Liveness;
|
||||
SymbolManager& SymMgr;
|
||||
const StackFrameContext *CurrentStackFrame;
|
||||
|
||||
public:
|
||||
SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr)
|
||||
: Liveness(liveness), SymMgr(symmgr) {}
|
||||
SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr,
|
||||
const StackFrameContext *currentStackFrame)
|
||||
: Liveness(liveness), SymMgr(symmgr), CurrentStackFrame(currentStackFrame)
|
||||
{}
|
||||
|
||||
~SymbolReaper() {}
|
||||
|
||||
@ -345,10 +350,8 @@ class SymbolReaper {
|
||||
return Liveness.isLive(Loc, ExprVal);
|
||||
}
|
||||
|
||||
bool isLive(const Stmt* Loc, const VarDecl* VD) const {
|
||||
return Liveness.isLive(Loc, VD);
|
||||
}
|
||||
|
||||
bool isLive(const Stmt* Loc, const VarRegion *VR) const;
|
||||
|
||||
void markLive(SymbolRef sym);
|
||||
bool maybeDead(SymbolRef sym);
|
||||
|
||||
|
@ -333,10 +333,11 @@ static bool isEqual(const clang::ProgramPoint& L,
|
||||
return L == R;
|
||||
}
|
||||
|
||||
static bool isPod() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -166,7 +166,7 @@ class BumpVector {
|
||||
private:
|
||||
/// grow - double the size of the allocated memory, guaranteeing space for at
|
||||
/// least one more element or MinSize if specified.
|
||||
void grow(BumpVectorContext &C, size_type MinSize = 0);
|
||||
void grow(BumpVectorContext &C, size_type MinSize = 1);
|
||||
|
||||
void construct_range(T *S, T *E, const T &Elt) {
|
||||
for (; S != E; ++S)
|
||||
|
@ -118,51 +118,51 @@ BUILTIN(__builtin_powf, "fff" , "nc")
|
||||
BUILTIN(__builtin_powl, "LdLdLd", "nc")
|
||||
|
||||
// Standard unary libc/libm functions with double/float/long double variants:
|
||||
BUILTIN(__builtin_acos , "dd" , "nc")
|
||||
BUILTIN(__builtin_acosf, "ff" , "nc")
|
||||
BUILTIN(__builtin_acosl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_asin , "dd" , "nc")
|
||||
BUILTIN(__builtin_asinf, "ff" , "nc")
|
||||
BUILTIN(__builtin_asinl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_atan , "dd" , "nc")
|
||||
BUILTIN(__builtin_atanf, "ff" , "nc")
|
||||
BUILTIN(__builtin_atanl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_ceil , "dd" , "nc")
|
||||
BUILTIN(__builtin_ceilf, "ff" , "nc")
|
||||
BUILTIN(__builtin_ceill, "LdLd", "nc")
|
||||
BUILTIN(__builtin_cos , "dd" , "nc")
|
||||
BUILTIN(__builtin_cosf, "ff" , "nc")
|
||||
BUILTIN(__builtin_cosh , "dd" , "nc")
|
||||
BUILTIN(__builtin_coshf, "ff" , "nc")
|
||||
BUILTIN(__builtin_coshl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_cosl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_exp , "dd" , "nc")
|
||||
BUILTIN(__builtin_expf, "ff" , "nc")
|
||||
BUILTIN(__builtin_expl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_floor , "dd" , "nc")
|
||||
BUILTIN(__builtin_floorf, "ff" , "nc")
|
||||
BUILTIN(__builtin_floorl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_log , "dd" , "nc")
|
||||
BUILTIN(__builtin_log10 , "dd" , "nc")
|
||||
BUILTIN(__builtin_log10f, "ff" , "nc")
|
||||
BUILTIN(__builtin_log10l, "LdLd", "nc")
|
||||
BUILTIN(__builtin_logf, "ff" , "nc")
|
||||
BUILTIN(__builtin_logl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_sin , "dd" , "nc")
|
||||
BUILTIN(__builtin_sinf, "ff" , "nc")
|
||||
BUILTIN(__builtin_sinh , "dd" , "nc")
|
||||
BUILTIN(__builtin_sinhf, "ff" , "nc")
|
||||
BUILTIN(__builtin_sinhl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_sinl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_sqrt , "dd" , "nc")
|
||||
BUILTIN(__builtin_sqrtf, "ff" , "nc")
|
||||
BUILTIN(__builtin_sqrtl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_tan , "dd" , "nc")
|
||||
BUILTIN(__builtin_tanf, "ff" , "nc")
|
||||
BUILTIN(__builtin_tanh , "dd" , "nc")
|
||||
BUILTIN(__builtin_tanhf, "ff" , "nc")
|
||||
BUILTIN(__builtin_tanhl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_tanl, "LdLd", "nc")
|
||||
BUILTIN(__builtin_acos , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_acosf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_acosl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_asin , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_asinf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_asinl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_atan , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_atanf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_atanl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_ceil , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_ceilf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_ceill, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_cos , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_cosf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_cosh , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_coshf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_coshl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_cosl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_exp , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_expf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_expl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_floor , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_floorf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_floorl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_log , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_log10 , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_log10f, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_log10l, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_logf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_logl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_sin , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_sinf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_sinh , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_sinhf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_sinhl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_sinl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_sqrt , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_sqrtf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_sqrtl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_tan , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_tanf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_tanh , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_tanhf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_tanhl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_tanl, "LdLd", "Fnc")
|
||||
|
||||
// C99 complex builtins
|
||||
BUILTIN(__builtin_cabs, "dXd", "Fnc")
|
||||
|
@ -250,7 +250,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
|
||||
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
|
||||
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
|
||||
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
|
||||
BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLic", "")
|
||||
BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "")
|
||||
BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLic", "")
|
||||
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
|
||||
|
||||
|
@ -238,7 +238,6 @@ class Diagnostic {
|
||||
DiagnosticClient *getClient() { return Client; }
|
||||
const DiagnosticClient *getClient() const { return Client; }
|
||||
|
||||
|
||||
/// pushMappings - Copies the current DiagMappings and pushes the new copy
|
||||
/// onto the top of the stack.
|
||||
void pushMappings();
|
||||
@ -319,7 +318,7 @@ class Diagnostic {
|
||||
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
|
||||
/// and level. If this is the first request for this diagnosic, it is
|
||||
/// registered and created, otherwise the existing ID is returned.
|
||||
unsigned getCustomDiagID(Level L, const char *Message);
|
||||
unsigned getCustomDiagID(Level L, llvm::StringRef Message);
|
||||
|
||||
|
||||
/// ConvertArgToString - This method converts a diagnostic argument (as an
|
||||
|
@ -26,8 +26,8 @@ def note_type_being_defined : Note<
|
||||
/// e.g. to specify the '(' when we expected a ')'.
|
||||
def note_matching : Note<"to match this '%0'">;
|
||||
|
||||
def note_using_decl : Note<"using">;
|
||||
def note_also_found_decl : Note<"also found">;
|
||||
def note_using : Note<"using">;
|
||||
def note_also_found : Note<"also found">;
|
||||
|
||||
// Parse && Lex
|
||||
def err_expected_colon : Error<"expected ':'">;
|
||||
|
@ -60,6 +60,8 @@ def err_drv_I_dash_not_supported : Error<
|
||||
def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
|
||||
def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
|
||||
def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
|
||||
def err_drv_invalid_remap_file : Error<
|
||||
"invalid option '%0' not of the form <from-file>;<to-file>">;
|
||||
|
||||
def warn_drv_input_file_unused : Warning<
|
||||
"%0: '%1' input unused when '%2' is present">;
|
||||
@ -70,7 +72,7 @@ def warn_drv_unused_argument : Warning<
|
||||
def warn_drv_pipe_ignored_with_save_temps : Warning<
|
||||
"-pipe ignored because -save-temps specified">;
|
||||
def warn_drv_not_using_clang_cpp : Warning<
|
||||
"not using the clang prepreprocessor due to user override">;
|
||||
"not using the clang preprocessor due to user override">;
|
||||
def warn_drv_not_using_clang_cxx : Warning<
|
||||
"not using the clang compiler for C++ inputs">;
|
||||
def warn_drv_not_using_clang_arch : Warning<
|
||||
|
@ -15,8 +15,8 @@ def err_fe_error_reading_stdin : Error<"error reading stdin">;
|
||||
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
|
||||
def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
|
||||
def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
|
||||
def err_fe_invalid_code_complete_file
|
||||
: Error<"cannot locate code-completion file %0">, DefaultFatal;
|
||||
def err_fe_invalid_code_complete_file : Error<
|
||||
"cannot locate code-completion file %0">, DefaultFatal;
|
||||
def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
|
||||
DefaultFatal;
|
||||
def err_fe_dependency_file_requires_MT : Error<
|
||||
@ -29,6 +29,36 @@ def err_fe_unable_to_find_fixit_file : Error<
|
||||
"FIX-IT could not find file '%0'">;
|
||||
def err_fe_invalid_plugin_name : Error<
|
||||
"unable to find plugin '%0'">;
|
||||
def err_fe_expected_compiler_job : Error<
|
||||
"unable to handle compilation, expected exactly one compiler job in '%0'">;
|
||||
def err_fe_expected_clang_command : Error<
|
||||
"expected a clang compiler command">;
|
||||
def err_fe_remap_missing_to_file : Error<
|
||||
"could not remap file '%0' to the contents of file '%1'">, DefaultFatal;
|
||||
def err_fe_remap_missing_from_file : Error<
|
||||
"could not remap from missing file '%0'">, DefaultFatal;
|
||||
def err_fe_unable_to_load_pch : Error<
|
||||
"unable to load PCH file">;
|
||||
def err_fe_unable_to_load_plugin : Error<
|
||||
"unable to load plugin '%0': '%1'">;
|
||||
def err_fe_unable_to_create_target : Error<
|
||||
"unable to create target: '%0'">;
|
||||
def err_fe_unable_to_interface_with_target : Error<
|
||||
"unable to interface with target machine">;
|
||||
def err_fe_unable_to_read_pch_file : Error<
|
||||
"unable to read PCH file: '%0'">;
|
||||
def err_fe_not_a_pch_file : Error<
|
||||
"input is not a PCH file: '%0'">;
|
||||
def err_fe_pch_malformed_block : Error<
|
||||
"malformed block record in PCH file: '%0'">;
|
||||
def err_fe_pch_error_at_end_block : Error<
|
||||
"error at end of module block in PCH file: '%0'">;
|
||||
def err_fe_unable_to_open_output : Error<
|
||||
"unable to open output file '%0': '%1'">;
|
||||
def err_fe_pth_file_has_no_source_header : Error<
|
||||
"PTH file '%0' does not designate an original source header file for -include-pth">;
|
||||
def warn_fe_macro_contains_embedded_newline : Warning<
|
||||
"macro '%0' contains embedded newline, text after the newline is ignored.">;
|
||||
|
||||
def err_verify_bogus_characters : Error<
|
||||
"bogus characters before '{{' in expected string">;
|
||||
@ -45,6 +75,8 @@ def note_fixit_in_macro : Note<
|
||||
def note_fixit_failed : Note<
|
||||
"FIX-IT unable to apply suggested code changes">;
|
||||
def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">;
|
||||
def note_fixit_main_file_unchanged : Note<
|
||||
"main file unchanged">;
|
||||
def warn_fixit_no_changes : Note<
|
||||
"FIX-IT detected errors it could not fix; no output will be generated">;
|
||||
|
||||
|
@ -113,6 +113,7 @@ def Reorder : DiagGroup<"reorder">;
|
||||
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
|
||||
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
|
||||
def : DiagGroup<"variadic-macros">;
|
||||
def VariadicMacros : DiagGroup<"variadic-macros">;
|
||||
def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
|
||||
def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
|
||||
def : DiagGroup<"write-strings">;
|
||||
|
@ -51,6 +51,9 @@ def err_empty_character : Error<"empty character constant">;
|
||||
def err_unterminated_block_comment : Error<"unterminated /* comment">;
|
||||
def err_invalid_character_to_charify : Error<
|
||||
"invalid argument to convert to character">;
|
||||
|
||||
def err_conflict_marker : Error<"version control conflict marker in file">;
|
||||
|
||||
def ext_multichar_character_literal : ExtWarn<
|
||||
"multi-character character constant">, InGroup<MultiChar>;
|
||||
def ext_four_char_character_literal : Extension<
|
||||
@ -150,9 +153,10 @@ def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
|
||||
def ext_pp_bad_vaargs_use : Extension<
|
||||
"__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">;
|
||||
def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">;
|
||||
def ext_variadic_macro : Extension<"variadic macros were introduced in C99">;
|
||||
def ext_variadic_macro : Extension<"variadic macros were introduced in C99">,
|
||||
InGroup<VariadicMacros>;
|
||||
def ext_named_variadic_macro : Extension<
|
||||
"named variadic macros are a GNU extension">;
|
||||
"named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
|
||||
def ext_embedded_directive : Extension<
|
||||
"embedding a directive within macro arguments is not portable">;
|
||||
def ext_missing_varargs_arg : Extension<
|
||||
@ -160,18 +164,11 @@ def ext_missing_varargs_arg : Extension<
|
||||
def ext_empty_fnmacro_arg : Extension<
|
||||
"empty macro arguments were standardized in C99">;
|
||||
|
||||
def ext_pp_base_file : Extension<"__BASE_FILE__ is a language extension">;
|
||||
def ext_pp_include_level : Extension<
|
||||
"__INCLUDE_LEVEL__ is a language extension">;
|
||||
def ext_pp_timestamp : Extension<"__TIMESTAMP__ is a language extension">;
|
||||
def ext_pp_counter : Extension<
|
||||
"__COUNTER__ is a language extension">;
|
||||
|
||||
def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
|
||||
def err_pp_hash_error : Error<"#error%0">;
|
||||
def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
|
||||
def err_pp_error_opening_file : Error<
|
||||
"error opening file '%0'">, DefaultFatal;
|
||||
"error opening file '%0': %1">, DefaultFatal;
|
||||
def err_pp_empty_filename : Error<"empty filename">;
|
||||
def err_pp_include_too_deep : Error<"#include nested too deeply">;
|
||||
def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">;
|
||||
|
@ -166,6 +166,8 @@ def err_use_of_tag_name_without_tag : Error<
|
||||
"use of tagged type %0 without '%1' tag">;
|
||||
def err_expected_ident_in_using : Error<
|
||||
"expected an identifier in using directive">;
|
||||
def err_unexected_colon_in_nested_name_spec : Error<
|
||||
"unexpected ':' in nested name specifier">;
|
||||
|
||||
/// Objective-C parser diagnostics
|
||||
def err_objc_no_attributes_on_category : Error<
|
||||
|
@ -105,7 +105,11 @@ def err_using_typename_non_type : Error<
|
||||
"'typename' keyword used on a non-type">;
|
||||
def err_using_dependent_value_is_type : Error<
|
||||
"dependent using declaration resolved to type without 'typename'">;
|
||||
def err_using_decl_nested_name_specifier_is_not_a_base_class : Error<
|
||||
def err_using_decl_nested_name_specifier_is_not_class : Error<
|
||||
"using declaration in class refers into '%0', which is not a class">;
|
||||
def err_using_decl_nested_name_specifier_is_current_class : Error<
|
||||
"using declaration refers to its own class">;
|
||||
def err_using_decl_nested_name_specifier_is_not_base_class : Error<
|
||||
"using declaration refers into '%0', which is not a base class of %1">;
|
||||
def err_using_decl_can_not_refer_to_class_member : Error<
|
||||
"using declaration can not refer to class member">;
|
||||
@ -117,8 +121,17 @@ def err_using_decl_destructor : Error<
|
||||
"using declaration can not refer to a destructor">;
|
||||
def err_using_decl_template_id : Error<
|
||||
"using declaration can not refer to a template specialization">;
|
||||
def note_using_decl_target : Note<
|
||||
"target of using declaration">;
|
||||
def note_using_decl_target : Note<"target of using declaration">;
|
||||
def note_using_decl_conflict : Note<"conflicting declaration">;
|
||||
def err_using_decl_redeclaration : Error<"redeclaration of using decl">;
|
||||
def err_using_decl_conflict : Error<
|
||||
"target of using declaration conflicts with declaration already in scope">;
|
||||
def err_using_decl_conflict_reverse : Error<
|
||||
"declaration conflicts with target of using declaration already in scope">;
|
||||
def note_using_decl : Note<"%select{|previous }0using declaration">;
|
||||
|
||||
def warn_access_decl_deprecated : Warning<
|
||||
"access declarations are deprecated; use using declarations instead">;
|
||||
|
||||
def err_invalid_thread : Error<
|
||||
"'__thread' is only allowed on variable declarations">;
|
||||
@ -186,7 +199,6 @@ def warn_pragma_pack_invalid_alignment : Warning<
|
||||
"expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">;
|
||||
// Follow the MSVC implementation.
|
||||
def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
|
||||
// FIXME: Dehardcode.
|
||||
def warn_pragma_pack_pop_identifer_and_alignment : Warning<
|
||||
"specifying both a name and alignment to 'pop' is undefined">;
|
||||
def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
|
||||
@ -441,7 +453,8 @@ def err_implicit_object_parameter_init : Error<
|
||||
"of type %1">;
|
||||
|
||||
def note_field_decl : Note<"member is declared here">;
|
||||
def note_previous_class_decl : Note<
|
||||
def note_bitfield_decl : Note<"bit-field is declared here">;
|
||||
def note_previous_decl : Note<
|
||||
"%0 declared here">;
|
||||
def note_member_synthesized_at : Note<
|
||||
"implicit default %select{constructor|copy constructor|"
|
||||
@ -521,14 +534,35 @@ def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lval
|
||||
def err_not_reference_to_const_init : Error<
|
||||
"non-const lvalue reference to type %0 cannot be initialized "
|
||||
"with a %1 of type %2">;
|
||||
def err_lvalue_reference_bind_to_temporary : Error<
|
||||
"non-const lvalue reference to type %0 cannot bind to a temporary of type "
|
||||
"%1">;
|
||||
def err_lvalue_reference_bind_to_unrelated : Error<
|
||||
"non-const lvalue reference to type %0 cannot bind to a value of unrelated "
|
||||
"type %1">;
|
||||
def err_reference_bind_drops_quals : Error<
|
||||
"binding of reference to type %0 to a value of type %1 drops qualifiers">;
|
||||
def err_reference_bind_failed : Error<
|
||||
"reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type "
|
||||
"%2">;
|
||||
def err_reference_bind_init_list : Error<
|
||||
"reference to type %0 cannot bind to an initializer list">;
|
||||
def err_init_list_bad_dest_type : Error<
|
||||
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
|
||||
"list">;
|
||||
|
||||
// FIXME: passing in an English string as %1!
|
||||
def err_reference_init_drops_quals : Error<
|
||||
"initialization of reference to type %0 with a %1 of type %2 drops "
|
||||
"qualifiers">;
|
||||
def err_reference_bind_to_bitfield : Error<
|
||||
"%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
|
||||
def err_reference_var_requires_init : Error<
|
||||
"declaration of reference variable %0 requires an initializer">;
|
||||
def err_const_var_requires_init : Error<
|
||||
"declaration of const variable '%0' requires an initializer">;
|
||||
def err_reference_has_multiple_inits : Error<
|
||||
"reference cannot be initialized with multiple values">;
|
||||
def err_init_non_aggr_init_list : Error<
|
||||
"initialization of non-aggregate type %0 with an initializer list">;
|
||||
def err_init_reference_member_uninitialized : Error<
|
||||
@ -934,6 +968,11 @@ def err_template_variable_noparams : Error<
|
||||
"extraneous 'template<>' in declaration of variable %0">;
|
||||
def err_template_tag_noparams : Error<
|
||||
"extraneous 'template<>' in declaration of %0 %1">;
|
||||
def err_template_decl_ref : Error<
|
||||
"cannot refer to class template %0 without a template argument list">;
|
||||
|
||||
def err_typedef_in_def_scope : Error<
|
||||
"cannot use typedef %0 in scope specifier for out-of-line declaration">;
|
||||
|
||||
// C++ Template Argument Lists
|
||||
def err_template_arg_list_different_arity : Error<
|
||||
@ -1261,7 +1300,10 @@ def warn_missing_prototype : Warning<
|
||||
"no previous prototype for function %0">,
|
||||
InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
|
||||
def err_redefinition : Error<"redefinition of %0">;
|
||||
|
||||
def err_definition_of_implicitly_declared_member : Error<
|
||||
"definition of implicitly declared %select{constructor|copy constructor|"
|
||||
"copy assignment operator|destructor}1">;
|
||||
|
||||
def warn_redefinition_of_typedef : Warning<
|
||||
"redefinition of typedef %0 is invalid in C">,
|
||||
InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
|
||||
@ -1515,6 +1557,8 @@ def err_typecheck_member_reference_ivar : Error<
|
||||
"%0 does not have a member named %1">;
|
||||
def err_typecheck_member_reference_arrow : Error<
|
||||
"member reference type %0 is not a pointer">;
|
||||
def err_typecheck_member_reference_suggestion : Error<
|
||||
"member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">;
|
||||
def err_typecheck_member_reference_type : Error<
|
||||
"cannot refer to type member %0 with '%select{.|->}1'">;
|
||||
def err_typecheck_member_reference_unknown : Error<
|
||||
@ -1564,6 +1608,9 @@ def warn_tentative_incomplete_array : Warning<
|
||||
def err_typecheck_incomplete_array_needs_initializer : Error<
|
||||
"definition of variable with array type needs an explicit size "
|
||||
"or an initializer">;
|
||||
def err_array_init_not_init_list : Error<
|
||||
"array initializater must be an initializer "
|
||||
"list%select{| or string literal}0">;
|
||||
|
||||
def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
|
||||
def err_typecheck_sclass_fscope : Error<
|
||||
@ -1649,6 +1696,7 @@ def warn_printf_nonliteral : Warning<
|
||||
|
||||
def err_unexpected_interface : Error<
|
||||
"unexpected interface name %0: expected expression">;
|
||||
def err_ref_non_value : Error<"%0 does not refer to a value">;
|
||||
def err_property_not_found : Error<
|
||||
"property %0 not found on object of type %1">;
|
||||
def ext_gnu_void_ptr : Extension<
|
||||
@ -1849,7 +1897,10 @@ def err_typecheck_bool_condition : Error<
|
||||
def err_typecheck_ambiguous_condition : Error<
|
||||
"conversion from %0 to %1 is ambiguous">;
|
||||
def err_typecheck_nonviable_condition : Error<
|
||||
"no viable conversion from %0 to %1 is possible">;
|
||||
"no viable conversion from %0 to %1">;
|
||||
def err_typecheck_deleted_function : Error<
|
||||
"conversion function from %0 to %1 invokes a deleted function">;
|
||||
|
||||
def err_expected_class_or_namespace : Error<"expected a class or namespace">;
|
||||
def err_invalid_declarator_scope : Error<
|
||||
"definition or redeclaration of %0 not in a namespace enclosing %1">;
|
||||
@ -1963,7 +2014,8 @@ def err_cannot_pass_objc_interface_to_vararg : Error<
|
||||
|
||||
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
|
||||
"cannot pass object of non-POD type %0 through variadic "
|
||||
"%select{function|block|method|constructor}1; call will abort at runtime">;
|
||||
"%select{function|block|method|constructor}1; call will abort at runtime">,
|
||||
InGroup<DiagGroup<"non-pod-varargs">>, DefaultError;
|
||||
|
||||
def err_typecheck_call_invalid_ordered_compare : Error<
|
||||
"ordered compare requires two args of floating point type (%0 and %1)">;
|
||||
@ -2047,12 +2099,6 @@ def err_overload_expr_requires_non_zero_constant : Error<
|
||||
def err_overload_incorrect_fntype : Error<
|
||||
"argument is not a function, or has wrong number of parameters">;
|
||||
|
||||
// FIXME: PASSING TYPES AS STRING.
|
||||
def err_overload_no_match : Error<
|
||||
"no matching overload found for arguments of type '%0'">;
|
||||
def err_overload_multiple_match : Error<
|
||||
"more than one matching function found in __builtin_overload">;
|
||||
|
||||
// C++ member initializers.
|
||||
def err_only_constructors_take_base_inits : Error<
|
||||
"only constructors take base initializers">;
|
||||
@ -2176,10 +2222,6 @@ def err_operator_overload_needs_class_or_enum : Error<
|
||||
def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">;
|
||||
def err_operator_overload_static : Error<
|
||||
"overloaded %0 cannot be a static member function">;
|
||||
def err_operator_new_param_type : Error<
|
||||
"%0 takes type size_t (%1) as first parameter">;
|
||||
def err_operator_new_result_type : Error<
|
||||
"%0 must return type %1">;
|
||||
def err_operator_overload_default_arg : Error<
|
||||
"parameter of overloaded %0 cannot have a default argument">;
|
||||
def err_operator_overload_must_be : Error<
|
||||
@ -2192,6 +2234,31 @@ def err_operator_overload_post_incdec_must_be_int : Error<
|
||||
"parameter of overloaded post-%select{increment|decrement}1 operator must "
|
||||
"have type 'int' (not %0)">;
|
||||
|
||||
// C++ allocation and deallocation functions.
|
||||
def err_operator_new_delete_declared_in_namespace : Error<
|
||||
"%0 cannot be declared inside a namespace">;
|
||||
def err_operator_new_delete_declared_static : Error<
|
||||
"%0 cannot be declared static in global scope">;
|
||||
def err_operator_new_delete_invalid_result_type : Error<
|
||||
"%0 must return type %1">;
|
||||
def err_operator_new_delete_dependent_result_type : Error<
|
||||
"%0 cannot have a dependent return type; use %1 instead">;
|
||||
def err_operator_new_delete_too_few_parameters : Error<
|
||||
"%0 must have at least one parameter.">;
|
||||
def err_operator_new_delete_template_too_few_parameters : Error<
|
||||
"%0 template must have at least two parameters.">;
|
||||
|
||||
def err_operator_new_dependent_param_type : Error<
|
||||
"%0 cannot take a dependent type as first parameter; "
|
||||
"use size_t (%1) instead">;
|
||||
def err_operator_new_param_type : Error<
|
||||
"%0 takes type size_t (%1) as first parameter">;
|
||||
def err_operator_new_default_arg: Error<
|
||||
"parameter of %0 cannot have a default argument">;
|
||||
def err_operator_delete_dependent_param_type : Error<
|
||||
"%0 cannot take a dependent type as first parameter; use %1 instead">;
|
||||
def err_operator_delete_param_type : Error<
|
||||
"%0 takes type %1 as first parameter">;
|
||||
|
||||
// C++ conversion functions
|
||||
def err_conv_function_not_member : Error<
|
||||
@ -2371,7 +2438,9 @@ def err_altivec_empty_initializer : Error<"expected initializer">;
|
||||
def err_stack_const_level : Error<
|
||||
"level argument for a stack address builtin must be constant">;
|
||||
|
||||
def err_prefetch_invalid_argument : Error<
|
||||
def err_prefetch_invalid_arg_type : Error<
|
||||
"argument to __builtin_prefetch must be of integer type">;
|
||||
def err_prefetch_invalid_arg_ice : Error<
|
||||
"argument to __builtin_prefetch must be a constant integer">;
|
||||
def err_argument_invalid_range : Error<
|
||||
"argument should be a value from %0 to %1">;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef LLVM_CLANG_FILEMANAGER_H
|
||||
#define LLVM_CLANG_FILEMANAGER_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
@ -151,6 +152,9 @@ class FileManager {
|
||||
///
|
||||
unsigned NextFileUID;
|
||||
|
||||
/// \brief The virtual files that we have allocated.
|
||||
llvm::SmallVector<FileEntry *, 4> VirtualFileEntries;
|
||||
|
||||
// Statistics.
|
||||
unsigned NumDirLookups, NumFileLookups;
|
||||
unsigned NumDirCacheMisses, NumFileCacheMisses;
|
||||
@ -199,6 +203,11 @@ class FileManager {
|
||||
const FileEntry *getFile(const char *FilenameStart,
|
||||
const char *FilenameEnd);
|
||||
|
||||
/// \brief Retrieve a file entry for a "virtual" file that acts as
|
||||
/// if there were a file with the given name on disk. The file
|
||||
/// itself is not accessed.
|
||||
const FileEntry *getVirtualFile(const llvm::StringRef &Filename,
|
||||
off_t Size, time_t ModificationTime);
|
||||
void PrintStats() const;
|
||||
};
|
||||
|
||||
|
@ -532,9 +532,11 @@ struct DenseMapInfo<clang::Selector> {
|
||||
static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::Selector> { static const bool value = true; };
|
||||
|
||||
|
||||
// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which
|
||||
// are not guaranteed to be 8-byte aligned.
|
||||
|
@ -46,7 +46,7 @@ class LangOptions {
|
||||
unsigned LaxVectorConversions : 1;
|
||||
unsigned AltiVec : 1; // Support AltiVec-style vector initializers.
|
||||
unsigned Exceptions : 1; // Support exception handling.
|
||||
unsigned Rtti : 1; // Support rtti information.
|
||||
unsigned RTTI : 1; // Support RTTI information.
|
||||
|
||||
unsigned NeXTRuntime : 1; // Use NeXT runtime.
|
||||
unsigned Freestanding : 1; // Freestanding implementation
|
||||
@ -92,6 +92,7 @@ class LangOptions {
|
||||
|
||||
unsigned ElideConstructors : 1; // Whether C++ copy constructors should be
|
||||
// elided if possible.
|
||||
unsigned CatchUndefined :1; // Generate code to check for undefined ops.
|
||||
private:
|
||||
unsigned GC : 2; // Objective-C Garbage Collection modes. We
|
||||
// declare this enum as unsigned because MSVC
|
||||
@ -125,7 +126,7 @@ class LangOptions {
|
||||
CXXOperatorNames = PascalStrings = WritableStrings = 0;
|
||||
Exceptions = Freestanding = NoBuiltin = 0;
|
||||
NeXTRuntime = 1;
|
||||
Rtti = 1;
|
||||
RTTI = 1;
|
||||
LaxVectorConversions = 1;
|
||||
HeinousExtensions = 0;
|
||||
AltiVec = OpenCL = StackProtector = 0;
|
||||
@ -160,6 +161,7 @@ class LangOptions {
|
||||
|
||||
CharIsSigned = 1;
|
||||
ShortWChar = 0;
|
||||
CatchUndefined = 0;
|
||||
}
|
||||
|
||||
GCMode getGCMode() const { return (GCMode) GC; }
|
||||
|
@ -51,11 +51,11 @@ class PartialDiagnostic {
|
||||
/// This is used when the argument is not an std::string. The specific value
|
||||
/// is mangled into an intptr_t and the intepretation depends on exactly
|
||||
/// what sort of argument kind it is.
|
||||
mutable intptr_t DiagArgumentsVal[MaxArguments];
|
||||
intptr_t DiagArgumentsVal[MaxArguments];
|
||||
|
||||
/// DiagRanges - The list of ranges added to this diagnostic. It currently
|
||||
/// only support 10 ranges, could easily be extended if needed.
|
||||
mutable const SourceRange *DiagRanges[10];
|
||||
SourceRange DiagRanges[10];
|
||||
};
|
||||
|
||||
/// DiagID - The diagnostic ID.
|
||||
@ -81,25 +81,40 @@ class PartialDiagnostic {
|
||||
assert(DiagStorage->NumDiagRanges <
|
||||
llvm::array_lengthof(DiagStorage->DiagRanges) &&
|
||||
"Too many arguments to diagnostic!");
|
||||
DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = &R;
|
||||
DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R;
|
||||
}
|
||||
|
||||
void operator=(const PartialDiagnostic &); // DO NOT IMPLEMENT
|
||||
|
||||
public:
|
||||
PartialDiagnostic(unsigned DiagID)
|
||||
: DiagID(DiagID), DiagStorage(0) { }
|
||||
|
||||
PartialDiagnostic(const PartialDiagnostic &Other)
|
||||
: DiagID(Other.DiagID), DiagStorage(Other.DiagStorage) {
|
||||
Other.DiagID = 0;
|
||||
Other.DiagStorage = 0;
|
||||
: DiagID(Other.DiagID), DiagStorage(0)
|
||||
{
|
||||
if (Other.DiagStorage)
|
||||
DiagStorage = new Storage(*Other.DiagStorage);
|
||||
}
|
||||
|
||||
PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
|
||||
DiagID = Other.DiagID;
|
||||
if (Other.DiagStorage) {
|
||||
if (DiagStorage)
|
||||
*DiagStorage = *Other.DiagStorage;
|
||||
else
|
||||
DiagStorage = new Storage(*Other.DiagStorage);
|
||||
} else {
|
||||
delete DiagStorage;
|
||||
DiagStorage = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~PartialDiagnostic() {
|
||||
delete DiagStorage;
|
||||
}
|
||||
|
||||
|
||||
unsigned getDiagID() const { return DiagID; }
|
||||
|
||||
void Emit(const DiagnosticBuilder &DB) const {
|
||||
@ -114,7 +129,7 @@ class PartialDiagnostic {
|
||||
|
||||
// Add all ranges.
|
||||
for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i)
|
||||
DB.AddSourceRange(*DiagStorage->DiagRanges[i]);
|
||||
DB.AddSourceRange(DiagStorage->DiagRanges[i]);
|
||||
}
|
||||
|
||||
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
|
@ -21,6 +21,7 @@ namespace llvm {
|
||||
class MemoryBuffer;
|
||||
class raw_ostream;
|
||||
template <typename T> struct DenseMapInfo;
|
||||
template <typename T> struct isPodLike;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
@ -296,9 +297,12 @@ namespace llvm {
|
||||
static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::SourceLocation> { static const bool value = true; };
|
||||
template <>
|
||||
struct isPodLike<clang::FileID> { static const bool value = true; };
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -54,9 +54,6 @@ namespace SrcMgr {
|
||||
/// file. This is owned by the ContentCache object.
|
||||
mutable const llvm::MemoryBuffer *Buffer;
|
||||
|
||||
/// The line and column at which we should truncate the file.
|
||||
unsigned TruncateAtLine, TruncateAtColumn;
|
||||
|
||||
public:
|
||||
/// Reference to the file entry. This reference does not own
|
||||
/// the FileEntry object. It is possible for this to be NULL if
|
||||
@ -72,13 +69,10 @@ namespace SrcMgr {
|
||||
/// if SourceLineCache is non-null.
|
||||
unsigned NumLines;
|
||||
|
||||
/// FirstFID - First FileID that was created for this ContentCache.
|
||||
/// Represents the first source inclusion of the file associated with this
|
||||
/// ContentCache.
|
||||
mutable FileID FirstFID;
|
||||
|
||||
/// getBuffer - Returns the memory buffer for the associated content.
|
||||
const llvm::MemoryBuffer *getBuffer() const;
|
||||
/// getBuffer - Returns the memory buffer for the associated content. If
|
||||
/// there is an error opening this buffer the first time, this manufactures
|
||||
/// a temporary buffer and returns a non-empty error string.
|
||||
const llvm::MemoryBuffer *getBuffer(std::string *ErrorStr = 0) const;
|
||||
|
||||
/// getSize - Returns the size of the content encapsulated by this
|
||||
/// ContentCache. This can be the size of the source file or the size of an
|
||||
@ -96,28 +90,19 @@ namespace SrcMgr {
|
||||
Buffer = B;
|
||||
}
|
||||
|
||||
/// \brief Truncate this file at the given line and column.
|
||||
///
|
||||
/// \param Line the line on which to truncate the current file (1-based).
|
||||
/// \param Column the column at which to truncate the current file.
|
||||
/// (1-based).
|
||||
void truncateAt(unsigned Line, unsigned Column);
|
||||
|
||||
/// \brief Determines whether the file was artificially truncated with
|
||||
/// truncateAt().
|
||||
bool isTruncated() const { return TruncateAtLine && TruncateAtColumn; }
|
||||
|
||||
/// \brief Replace the existing buffer (which will be deleted)
|
||||
/// with the given buffer.
|
||||
void replaceBuffer(const llvm::MemoryBuffer *B);
|
||||
|
||||
ContentCache(const FileEntry *Ent = 0)
|
||||
: Buffer(0), TruncateAtLine(0), TruncateAtColumn(0), Entry(Ent),
|
||||
SourceLineCache(0), NumLines(0) {}
|
||||
: Buffer(0), Entry(Ent), SourceLineCache(0), NumLines(0) {}
|
||||
|
||||
~ContentCache();
|
||||
|
||||
/// The copy ctor does not allow copies where source object has either
|
||||
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
|
||||
/// is not transfered, so this is a logical error.
|
||||
ContentCache(const ContentCache &RHS)
|
||||
: Buffer(0), TruncateAtLine(0), TruncateAtColumn(0), SourceLineCache(0) {
|
||||
ContentCache(const ContentCache &RHS) : Buffer(0), SourceLineCache(0) {
|
||||
Entry = RHS.Entry;
|
||||
|
||||
assert (RHS.Buffer == 0 && RHS.SourceLineCache == 0
|
||||
@ -347,19 +332,13 @@ class SourceManager {
|
||||
mutable FileID LastRFIDForBeforeTUCheck;
|
||||
mutable bool LastResForBeforeTUCheck;
|
||||
|
||||
// Keep track of the file/line/column that we should truncate.
|
||||
const FileEntry *TruncateFile;
|
||||
unsigned TruncateAtLine;
|
||||
unsigned TruncateAtColumn;
|
||||
|
||||
// SourceManager doesn't support copy construction.
|
||||
explicit SourceManager(const SourceManager&);
|
||||
void operator=(const SourceManager&);
|
||||
public:
|
||||
SourceManager()
|
||||
: ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
|
||||
NumBinaryProbes(0), TruncateFile(0), TruncateAtLine(0),
|
||||
TruncateAtColumn(0) {
|
||||
: ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
|
||||
NumBinaryProbes(0) {
|
||||
clearIDTables();
|
||||
}
|
||||
~SourceManager();
|
||||
@ -428,14 +407,30 @@ class SourceManager {
|
||||
unsigned PreallocatedID = 0,
|
||||
unsigned Offset = 0);
|
||||
|
||||
/// \brief Retrieve the memory buffer associated with the given file.
|
||||
const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File);
|
||||
|
||||
/// \brief Override the contents of the given source file by providing an
|
||||
/// already-allocated buffer.
|
||||
///
|
||||
/// \param SourceFile the source file whose contents will be override.
|
||||
///
|
||||
/// \param Buffer the memory buffer whose contents will be used as the
|
||||
/// data in the given source file.
|
||||
///
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool overrideFileContents(const FileEntry *SourceFile,
|
||||
const llvm::MemoryBuffer *Buffer);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// FileID manipulation methods.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// getBuffer - Return the buffer for the specified FileID.
|
||||
///
|
||||
const llvm::MemoryBuffer *getBuffer(FileID FID) const {
|
||||
return getSLocEntry(FID).getFile().getContentCache()->getBuffer();
|
||||
/// getBuffer - Return the buffer for the specified FileID. If there is an
|
||||
/// error opening this buffer the first time, this manufactures a temporary
|
||||
/// buffer and returns a non-empty error string.
|
||||
const llvm::MemoryBuffer *getBuffer(FileID FID, std::string *Error = 0) const{
|
||||
return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Error);
|
||||
}
|
||||
|
||||
/// getFileEntryForID - Returns the FileEntry record for the provided FileID.
|
||||
@ -669,12 +664,6 @@ class SourceManager {
|
||||
/// \returns true if LHS source location comes before RHS, false otherwise.
|
||||
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
|
||||
|
||||
/// \brief Truncate the given file at the specified line/column.
|
||||
void truncateFileAt(const FileEntry *Entry, unsigned Line, unsigned Column);
|
||||
|
||||
/// \brief Determine whether this file was truncated.
|
||||
bool isTruncatedFile(FileID FID) const;
|
||||
|
||||
// Iterators over FileInfos.
|
||||
typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
|
||||
::const_iterator fileinfo_iterator;
|
||||
|
@ -324,6 +324,8 @@ KEYWORD(__is_enum , KEYCXX)
|
||||
KEYWORD(__is_pod , KEYCXX)
|
||||
KEYWORD(__is_polymorphic , KEYCXX)
|
||||
KEYWORD(__is_union , KEYCXX)
|
||||
// Tentative name - there's no implementation of std::is_literal_type yet.
|
||||
KEYWORD(__is_literal , KEYCXX)
|
||||
// FIXME: Add MS's traits, too.
|
||||
|
||||
// Apple Extension.
|
||||
|
@ -32,7 +32,8 @@ namespace clang {
|
||||
UTT_IsEnum,
|
||||
UTT_IsPOD,
|
||||
UTT_IsPolymorphic,
|
||||
UTT_IsUnion
|
||||
UTT_IsUnion,
|
||||
UTT_IsLiteral
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ def analysis_CheckerCFRef : Flag<"-checker-cfref">,
|
||||
def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
|
||||
HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
|
||||
def analysis_InlineCall : Flag<"-inline-call">,
|
||||
HelpText<"Experimental transfer function inling callees when its definition is available.">;
|
||||
HelpText<"Experimental transfer function inlining callees when its definition is available.">;
|
||||
|
||||
def analyzer_store : Separate<"-analyzer-store">,
|
||||
HelpText<"Source Code Analysis - Abstract Memory Store Models">;
|
||||
@ -73,6 +73,8 @@ def analyzer_output_EQ : Joined<"-analyzer-output=">,
|
||||
|
||||
def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">,
|
||||
HelpText<"Force the static analyzer to analyze functions defined in header files">;
|
||||
def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">,
|
||||
HelpText<"Analyze the definitions of blocks in addition to functions">;
|
||||
def analyzer_display_progress : Flag<"-analyzer-display-progress">,
|
||||
HelpText<"Emit verbose output about the analyzer's progress">;
|
||||
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
|
||||
@ -103,6 +105,8 @@ def disable_llvm_optzns : Flag<"-disable-llvm-optzns">,
|
||||
def disable_red_zone : Flag<"-disable-red-zone">,
|
||||
HelpText<"Do not emit code that uses the red zone.">;
|
||||
def g : Flag<"-g">, HelpText<"Generate source level debug information">;
|
||||
def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
|
||||
HelpText<"Generate runtime checks for undefined behavior.">;
|
||||
def fno_common : Flag<"-fno-common">,
|
||||
HelpText<"Compile common globals like normal definitions">;
|
||||
def no_implicit_float : Flag<"-no-implicit-float">,
|
||||
@ -117,13 +121,13 @@ def mdebug_pass : Separate<"-mdebug-pass">,
|
||||
HelpText<"Enable additional debug output">;
|
||||
def mdisable_fp_elim : Flag<"-mdisable-fp-elim">,
|
||||
HelpText<"Disable frame pointer elimination optimization">;
|
||||
def mfloat_abi : Flag<"-mfloat-abi">,
|
||||
def mfloat_abi : Separate<"-mfloat-abi">,
|
||||
HelpText<"The float ABI to use">;
|
||||
def mlimit_float_precision : Separate<"-mlimit-float-precision">,
|
||||
HelpText<"Limit float precision to the given value">;
|
||||
def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">,
|
||||
HelpText<"Do not put zero initialized data in the BSS">;
|
||||
def msoft_float : Separate<"-msoft-float">,
|
||||
def msoft_float : Flag<"-msoft-float">,
|
||||
HelpText<"Use software floating point">;
|
||||
def mrelocation_model : Separate<"-mrelocation-model">,
|
||||
HelpText<"The relocation model to use">;
|
||||
@ -149,7 +153,7 @@ def MP : Flag<"-MP">,
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def dump_build_information : Separate<"-dump-build-information">,
|
||||
MetaVarName<"filename">,
|
||||
MetaVarName<"<filename>">,
|
||||
HelpText<"output a dump of some build information to a file">;
|
||||
def fno_show_column : Flag<"-fno-show-column">,
|
||||
HelpText<"Do not include column number on diagnostics">;
|
||||
@ -172,7 +176,7 @@ def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-rang
|
||||
HelpText<"Print source range spans in numeric form">;
|
||||
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
|
||||
HelpText<"Print diagnostic name with mappable diagnostics">;
|
||||
def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"N">,
|
||||
def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">,
|
||||
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
|
||||
def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
|
||||
HelpText<"Use colors in diagnostics">;
|
||||
@ -185,28 +189,45 @@ def verify : Flag<"-verify">,
|
||||
// Frontend Options
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This isn't normally used, it is just here so we can parse a
|
||||
// CompilerInvocation out of a driver-derived argument vector.
|
||||
def cc1 : Flag<"-cc1">;
|
||||
|
||||
def code_completion_at : Separate<"-code-completion-at">,
|
||||
MetaVarName<"file:line:column">,
|
||||
MetaVarName<"<file>:<line>:<column>">,
|
||||
HelpText<"Dump code-completion information at a location">;
|
||||
def remap_file : Separate<"-remap-file">,
|
||||
MetaVarName<"<from>;<to>">,
|
||||
HelpText<"Replace the contents of the <from> file with the contents of the <to> file">;
|
||||
def code_completion_at_EQ : Joined<"-code-completion-at=">,
|
||||
Alias<code_completion_at>;
|
||||
def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">,
|
||||
HelpText<"Don't the \"debug\" code-completion print">;
|
||||
HelpText<"Don't use the \"debug\" code-completion print">;
|
||||
def code_completion_macros : Flag<"-code-completion-macros">,
|
||||
HelpText<"Include macros in code-completion results">;
|
||||
def disable_free : Flag<"-disable-free">,
|
||||
HelpText<"Disable freeing of memory on exit">;
|
||||
def empty_input_only : Flag<"-empty-input-only">,
|
||||
HelpText<"Force running on an empty input file">;
|
||||
def help : Flag<"-help">,
|
||||
HelpText<"Print this help text">;
|
||||
def _help : Flag<"--help">, Alias<help>;
|
||||
def x : Separate<"-x">, HelpText<"Input language type">;
|
||||
def cxx_inheritance_view : Separate<"-cxx-inheritance-view">,
|
||||
MetaVarName<"class name">,
|
||||
MetaVarName<"<class name>">,
|
||||
HelpText<"View C++ inheritance for a specified class">;
|
||||
def fixit_at : Separate<"-fixit-at">, MetaVarName<"source-location">,
|
||||
def fixit_at : Separate<"-fixit-at">, MetaVarName<"<source location>">,
|
||||
HelpText<"Perform Fix-It modifications at the given source location">;
|
||||
def o : Separate<"-o">, MetaVarName<"path">, HelpText<"Specify output file">;
|
||||
def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">;
|
||||
def load : Separate<"-load">, MetaVarName<"<dsopath>">,
|
||||
HelpText<"Load the named plugin (dynamic shared object)">;
|
||||
def plugin : Separate<"-plugin">,
|
||||
HelpText<"Use the named plugin action (use \"help\" to list available options)">;
|
||||
def resource_dir : Separate<"-resource-dir">,
|
||||
HelpText<"The directory which holds the compiler resource files">;
|
||||
def version : Flag<"-version">,
|
||||
HelpText<"Print the compiler version">;
|
||||
def _version : Flag<"--version">, Alias<version>;
|
||||
|
||||
def Action_Group : OptionGroup<"<action group>">;
|
||||
let Group = Action_Group in {
|
||||
@ -313,7 +334,7 @@ def fno_signed_char : Flag<"-fno-signed-char">,
|
||||
def fno_operator_names : Flag<"-fno-operator-names">,
|
||||
HelpText<"Do not treat C++ operator name keywords as synonyms for operators">;
|
||||
def fconstant_string_class : Separate<"-fconstant-string-class">,
|
||||
MetaVarName<"class name">,
|
||||
MetaVarName<"<class name>">,
|
||||
HelpText<"Specify the class to use for constant Objective-C string objects.">;
|
||||
def fobjc_gc : Flag<"-fobjc-gc">,
|
||||
HelpText<"Enable Objective-C garbage collection">;
|
||||
@ -326,7 +347,7 @@ def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">,
|
||||
def ftrapv : Flag<"-ftrapv">,
|
||||
HelpText<"Trap on integer overflow">;
|
||||
def pic_level : Separate<"-pic-level">,
|
||||
HelpText<"-Value for __PIC__">;
|
||||
HelpText<"Value for __PIC__">;
|
||||
def pthread : Flag<"-pthread">,
|
||||
HelpText<"Support POSIX threads in generated code">;
|
||||
def fpascal_strings : Flag<"-fpascal-strings">,
|
||||
@ -356,23 +377,24 @@ def nostdinc : Flag<"-nostdinc">,
|
||||
HelpText<"Disable standard #include directories">;
|
||||
def nobuiltininc : Flag<"-nobuiltininc">,
|
||||
HelpText<"Disable builtin #include directories">;
|
||||
def F : JoinedOrSeparate<"-F">, MetaVarName<"directory">,
|
||||
def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">,
|
||||
HelpText<"Add directory to framework include search path">;
|
||||
def I : JoinedOrSeparate<"-I">, MetaVarName<"directory">,
|
||||
def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">,
|
||||
HelpText<"Add directory to include search path">;
|
||||
def idirafter : Separate<"-idirafter">, MetaVarName<"directory">,
|
||||
def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">,
|
||||
HelpText<"Add directory to AFTER include search path">;
|
||||
def iquote : Separate<"-iquote">, MetaVarName<"directory">,
|
||||
def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
|
||||
HelpText<"Add directory to QUOTE include search path">;
|
||||
def isystem : Separate<"-isystem">, MetaVarName<"directory">,
|
||||
def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
|
||||
HelpText<"Add directory to SYSTEM include search path">;
|
||||
def iprefix : Separate<"-iprefix">, MetaVarName<"prefix">,
|
||||
def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">,
|
||||
HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
|
||||
def iwithprefix : Separate<"-iwithprefix">, MetaVarName<"dir">,
|
||||
def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">,
|
||||
HelpText<"Set directory to SYSTEM include search path with prefix">;
|
||||
def iwithprefixbefore : Separate<"-iwithprefixbefore">, MetaVarName<"dir">,
|
||||
def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">,
|
||||
MetaVarName<"<dir>">,
|
||||
HelpText<"Set directory to include search path with prefix">;
|
||||
def isysroot : Separate<"-isysroot">, MetaVarName<"dir">,
|
||||
def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">,
|
||||
HelpText<"Set the system root directory (usually /)">;
|
||||
def v : Flag<"-v">, HelpText<"Enable verbose output">;
|
||||
|
||||
@ -380,21 +402,21 @@ def v : Flag<"-v">, HelpText<"Enable verbose output">;
|
||||
// Preprocessor Options
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def D : JoinedOrSeparate<"-D">, MetaVarName<"macro">,
|
||||
def D : JoinedOrSeparate<"-D">, MetaVarName<"<macro>">,
|
||||
HelpText<"Predefine the specified macro">;
|
||||
def include_ : Separate<"-include">, MetaVarName<"file">, EnumName<"include">,
|
||||
def include_ : JoinedOrSeparate<"-include">, MetaVarName<"<file>">, EnumName<"include">,
|
||||
HelpText<"Include file before parsing">;
|
||||
def imacros : Separate<"-imacros">, MetaVarName<"file">,
|
||||
def imacros : JoinedOrSeparate<"-imacros">, MetaVarName<"<file>">,
|
||||
HelpText<"Include macros from file before parsing">;
|
||||
def include_pch : Separate<"-include-pch">, MetaVarName<"file">,
|
||||
def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">,
|
||||
HelpText<"Include precompiled header file">;
|
||||
def include_pth : Separate<"-include-pth">, MetaVarName<"file">,
|
||||
def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">,
|
||||
HelpText<"Include file before parsing">;
|
||||
def token_cache : Separate<"-token-cache">, MetaVarName<"path">,
|
||||
def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">,
|
||||
HelpText<"Use specified token cache file">;
|
||||
def U : JoinedOrSeparate<"-U">, MetaVarName<"macro">,
|
||||
def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">,
|
||||
HelpText<"Undefine the specified macro">;
|
||||
def undef : Flag<"-undef">, MetaVarName<"macro">,
|
||||
def undef : Flag<"-undef">, MetaVarName<"<macro>">,
|
||||
HelpText<"undef all system defines">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "clang/Driver/Phases.h"
|
||||
#include "clang/Driver/Util.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/System/Path.h" // FIXME: Kill when CompilationInfo
|
||||
// lands.
|
||||
@ -112,9 +113,9 @@ class Driver {
|
||||
std::list<std::string> ResultFiles;
|
||||
|
||||
public:
|
||||
Driver(const char *_Name, const char *_Dir,
|
||||
const char *_DefaultHostTriple,
|
||||
const char *_DefaultImageName,
|
||||
Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
|
||||
llvm::StringRef _DefaultHostTriple,
|
||||
llvm::StringRef _DefaultImageName,
|
||||
bool IsProduction, Diagnostic &_Diags);
|
||||
~Driver();
|
||||
|
||||
|
@ -22,7 +22,8 @@ using llvm::dyn_cast_or_null;
|
||||
|
||||
namespace clang {
|
||||
namespace driver {
|
||||
class Command;
|
||||
class Command;
|
||||
class Tool;
|
||||
|
||||
class Job {
|
||||
public:
|
||||
@ -55,6 +56,9 @@ class Command : public Job {
|
||||
/// Source - The action which caused the creation of this job.
|
||||
const Action &Source;
|
||||
|
||||
/// Tool - The tool which caused the creation of this job.
|
||||
const Tool &Creator;
|
||||
|
||||
/// The executable to run.
|
||||
const char *Executable;
|
||||
|
||||
@ -63,12 +67,15 @@ class Command : public Job {
|
||||
ArgStringList Arguments;
|
||||
|
||||
public:
|
||||
Command(const Action &_Source, const char *_Executable,
|
||||
Command(const Action &_Source, const Tool &_Creator, const char *_Executable,
|
||||
const ArgStringList &_Arguments);
|
||||
|
||||
/// getSource - Return the Action which caused the creation of this job.
|
||||
const Action &getSource() const { return Source; }
|
||||
|
||||
/// getCreator - Return the Tool which caused the creation of this job.
|
||||
const Tool &getCreator() const { return Creator; }
|
||||
|
||||
const char *getExecutable() const { return Executable; }
|
||||
|
||||
const ArgStringList &getArguments() const { return Arguments; }
|
||||
|
@ -77,11 +77,17 @@ def RenderSeparate : OptionFlag;
|
||||
// lines that use it.
|
||||
def Unsupported : OptionFlag;
|
||||
|
||||
// HelpHidden - The option should not be displayed in --help, even if it has
|
||||
// help text. Clients *can* use this in conjuction with the OptTable::PrintHelp
|
||||
// arguments to implement hidden help groups.
|
||||
def HelpHidden : OptionFlag;
|
||||
|
||||
// Define the option group class.
|
||||
|
||||
class OptionGroup<string name> {
|
||||
string EnumName = ?; // Uses the def name if undefined.
|
||||
string Name = name;
|
||||
string HelpText = ?;
|
||||
OptionGroup Group = ?;
|
||||
}
|
||||
|
||||
|
@ -13,17 +13,22 @@
|
||||
#include "clang/Driver/OptSpecifier.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
namespace driver {
|
||||
namespace options {
|
||||
enum DriverFlag {
|
||||
DriverOption = (1 << 0),
|
||||
LinkerInput = (1 << 1),
|
||||
NoArgumentUnused = (1 << 2),
|
||||
RenderAsInput = (1 << 3),
|
||||
RenderJoined = (1 << 4),
|
||||
RenderSeparate = (1 << 5),
|
||||
Unsupported = (1 << 6)
|
||||
HelpHidden = (1 << 1),
|
||||
LinkerInput = (1 << 2),
|
||||
NoArgumentUnused = (1 << 3),
|
||||
RenderAsInput = (1 << 4),
|
||||
RenderJoined = (1 << 5),
|
||||
RenderSeparate = (1 << 6),
|
||||
Unsupported = (1 << 7)
|
||||
};
|
||||
}
|
||||
|
||||
@ -113,6 +118,17 @@ namespace options {
|
||||
return getInfo(id).Kind;
|
||||
}
|
||||
|
||||
/// getOptionGroupID - Get the group id for the given option.
|
||||
unsigned getOptionGroupID(OptSpecifier id) const {
|
||||
return getInfo(id).GroupID;
|
||||
}
|
||||
|
||||
/// isOptionHelpHidden - Should the help for the given option be hidden by
|
||||
/// default.
|
||||
bool isOptionHelpHidden(OptSpecifier id) const {
|
||||
return getInfo(id).Flags & options::HelpHidden;
|
||||
}
|
||||
|
||||
/// getOptionHelpText - Get the help text to use to describe this option.
|
||||
const char *getOptionHelpText(OptSpecifier id) const {
|
||||
return getInfo(id).HelpText;
|
||||
@ -156,6 +172,15 @@ namespace options {
|
||||
const char **ArgEnd,
|
||||
unsigned &MissingArgIndex,
|
||||
unsigned &MissingArgCount) const;
|
||||
|
||||
/// PrintHelp - Render the help text for an option table.
|
||||
///
|
||||
/// \param OS - The stream to write the help text to.
|
||||
/// \param Name - The name to use in the usage line.
|
||||
/// \param Title - The title to use in the usage line.
|
||||
/// \param ShowHidden - Whether help-hidden arguments should be shown.
|
||||
void PrintHelp(llvm::raw_ostream &OS, const char *Name,
|
||||
const char *Title, bool ShowHidden = false) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,55 @@ def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">,
|
||||
// = => _EQ
|
||||
// C++ => CXX
|
||||
|
||||
// Developer Driver Options
|
||||
|
||||
def ccc_Group : OptionGroup<"<clang internal options>">;
|
||||
def ccc_driver_Group : OptionGroup<"<clang driver internal options>">,
|
||||
Group<ccc_Group>, HelpText<"DRIVER OPTIONS">;
|
||||
def ccc_debug_Group : OptionGroup<"<clang debug/development internal options>">,
|
||||
Group<ccc_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">;
|
||||
|
||||
class CCCDriverOpt : Group<ccc_driver_Group>, Flags<[DriverOption, HelpHidden]>;
|
||||
def ccc_cxx : Flag<"-ccc-cxx">, CCCDriverOpt,
|
||||
HelpText<"Act as a C++ driver">;
|
||||
def ccc_echo : Flag<"-ccc-echo">, CCCDriverOpt,
|
||||
HelpText<"Echo commands before running them">;
|
||||
def ccc_gcc_name : Separate<"-ccc-gcc-name">, CCCDriverOpt,
|
||||
HelpText<"Name for native GCC compiler">,
|
||||
MetaVarName<"<gcc-path>">;
|
||||
def ccc_clang_cxx : Flag<"-ccc-clang-cxx">, CCCDriverOpt,
|
||||
HelpText<"Enable the clang compiler for C++">;
|
||||
def ccc_no_clang_cxx : Flag<"-ccc-no-clang-cxx">, CCCDriverOpt,
|
||||
HelpText<"Disable the clang compiler for C++">;
|
||||
def ccc_no_clang : Flag<"-ccc-no-clang">, CCCDriverOpt,
|
||||
HelpText<"Disable the clang compiler">;
|
||||
def ccc_no_clang_cpp : Flag<"-ccc-no-clang-cpp">, CCCDriverOpt,
|
||||
HelpText<"Disable the clang preprocessor">;
|
||||
def ccc_clang_archs : Separate<"-ccc-clang-archs">, CCCDriverOpt,
|
||||
HelpText<"Comma separate list of architectures to use the clang compiler for">,
|
||||
MetaVarName<"<arch-list>">;
|
||||
def ccc_pch_is_pch : Flag<"-ccc-pch-is-pch">, CCCDriverOpt,
|
||||
HelpText<"Use lazy PCH for precompiled headers">;
|
||||
def ccc_pch_is_pth : Flag<"-ccc-pch-is-pth">, CCCDriverOpt,
|
||||
HelpText<"Use pretokenized headers for precompiled headers">;
|
||||
|
||||
class CCCDebugOpt : Group<ccc_debug_Group>, Flags<[DriverOption, HelpHidden]>;
|
||||
def ccc_host_triple : Separate<"-ccc-host-triple">, CCCDebugOpt,
|
||||
HelpText<"Simulate running on the given target">;
|
||||
def ccc_install_dir : Separate<"-ccc-install-dir">, CCCDebugOpt,
|
||||
HelpText<"Simulate installation in the given directory">;
|
||||
def ccc_print_options : Flag<"-ccc-print-options">, CCCDebugOpt,
|
||||
HelpText<"Dump parsed command line arguments">;
|
||||
def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt,
|
||||
HelpText<"Dump list of actions to perform">;
|
||||
def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt,
|
||||
HelpText<"Show bindings of tools to actions">;
|
||||
|
||||
// Make sure all other -ccc- options are rejected.
|
||||
def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
|
||||
|
||||
// Standard Options
|
||||
|
||||
def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>,
|
||||
HelpText<"Print the commands to run for this compilation">;
|
||||
def A : JoinedOrSeparate<"-A">;
|
||||
@ -187,6 +236,8 @@ def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>;
|
||||
def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>;
|
||||
def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>;
|
||||
def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>;
|
||||
def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
|
||||
Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">;
|
||||
def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>;
|
||||
def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>;
|
||||
def fcommon : Flag<"-fcommon">, Group<f_Group>;
|
||||
@ -277,6 +328,9 @@ def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>;
|
||||
def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>;
|
||||
def framework : Separate<"-framework">, Flags<[LinkerInput]>;
|
||||
def frtti : Flag<"-frtti">, Group<f_Group>;
|
||||
def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>;
|
||||
def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>;
|
||||
def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>;
|
||||
def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>;
|
||||
def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>;
|
||||
def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>;
|
||||
@ -315,7 +369,7 @@ def init : Separate<"-init">;
|
||||
def install__name : Separate<"-install_name">;
|
||||
def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>;
|
||||
def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>;
|
||||
def isysroot : JoinedOrSeparate<"-isysroot">, Group<i_Group>;
|
||||
def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>;
|
||||
def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>;
|
||||
def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>;
|
||||
def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>;
|
||||
@ -373,6 +427,8 @@ def multiply__defined : Separate<"-multiply_defined">;
|
||||
def mwarn_nonportable_cfstrings : Flag<"-mwarn-nonportable-cfstrings">, Group<m_Group>;
|
||||
def m_Separate : Separate<"-m">, Group<m_Group>;
|
||||
def m_Joined : Joined<"-m">, Group<m_Group>;
|
||||
def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[DriverOption, HelpHidden]>,
|
||||
HelpText<"Use relative instead of canonical paths">;
|
||||
def no_cpp_precomp : Flag<"-no-cpp-precomp">;
|
||||
def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>;
|
||||
def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">;
|
||||
|
@ -94,9 +94,9 @@ ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP,
|
||||
bool SyntaxHighlight = true,
|
||||
bool HighlightMacros = true);
|
||||
|
||||
// PCH generator: generates a precompiled header file; this file can be
|
||||
// used later with the PCHReader (clang-cc option -include-pch)
|
||||
// to speed up compile times.
|
||||
// PCH generator: generates a precompiled header file; this file can be used
|
||||
// later with the PCHReader (clang -cc1 option -include-pch) to speed up compile
|
||||
// times.
|
||||
ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
|
||||
llvm::raw_ostream *OS,
|
||||
const char *isysroot = 0);
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "clang/Frontend/TextDiagnosticBuffer.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
@ -32,14 +33,12 @@ class HeaderSearch;
|
||||
class Preprocessor;
|
||||
class SourceManager;
|
||||
class TargetInfo;
|
||||
class TextDiagnosticBuffer;
|
||||
|
||||
using namespace idx;
|
||||
|
||||
/// \brief Utility class for loading a ASTContext from a PCH file.
|
||||
///
|
||||
class ASTUnit {
|
||||
Diagnostic Diags;
|
||||
FileManager FileMgr;
|
||||
|
||||
SourceManager SourceMgr;
|
||||
@ -48,22 +47,39 @@ class ASTUnit {
|
||||
llvm::OwningPtr<Preprocessor> PP;
|
||||
llvm::OwningPtr<ASTContext> Ctx;
|
||||
bool tempFile;
|
||||
|
||||
|
||||
// OnlyLocalDecls - when true, walking this AST should only visit declarations
|
||||
// that come from the AST itself, not from included precompiled headers.
|
||||
// FIXME: This is temporary; eventually, CIndex will always do this.
|
||||
bool OnlyLocalDecls;
|
||||
|
||||
|
||||
/// Track whether the main file was loaded from an AST or not.
|
||||
bool MainFileIsAST;
|
||||
|
||||
/// Track the top-level decls which appeared in an ASTUnit which was loaded
|
||||
/// from a source file.
|
||||
//
|
||||
// FIXME: This is just an optimization hack to avoid deserializing large parts
|
||||
// of a PCH file when using the Index library on an ASTUnit loaded from
|
||||
// source. In the long term we should make the Index library use efficient and
|
||||
// more scalable search mechanisms.
|
||||
std::vector<Decl*> TopLevelDecls;
|
||||
|
||||
/// The name of the original source file used to generate this ASTUnit.
|
||||
std::string OriginalSourceFile;
|
||||
|
||||
// Critical optimization when using clang_getCursor().
|
||||
ASTLocation LastLoc;
|
||||
|
||||
|
||||
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
|
||||
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
|
||||
|
||||
public:
|
||||
ASTUnit(DiagnosticClient *diagClient = NULL);
|
||||
ASTUnit(bool MainFileIsAST);
|
||||
~ASTUnit();
|
||||
|
||||
bool isMainFileAST() const { return MainFileIsAST; }
|
||||
|
||||
const SourceManager &getSourceManager() const { return SourceMgr; }
|
||||
SourceManager &getSourceManager() { return SourceMgr; }
|
||||
|
||||
@ -73,37 +89,38 @@ class ASTUnit {
|
||||
const ASTContext &getASTContext() const { return *Ctx.get(); }
|
||||
ASTContext &getASTContext() { return *Ctx.get(); }
|
||||
|
||||
const Diagnostic &getDiagnostic() const { return Diags; }
|
||||
Diagnostic &getDiagnostic() { return Diags; }
|
||||
|
||||
const FileManager &getFileManager() const { return FileMgr; }
|
||||
FileManager &getFileManager() { return FileMgr; }
|
||||
|
||||
|
||||
const std::string &getOriginalSourceFileName();
|
||||
const std::string &getPCHFileName();
|
||||
|
||||
void unlinkTemporaryFile() { tempFile = true; }
|
||||
|
||||
|
||||
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
|
||||
|
||||
|
||||
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
|
||||
ASTLocation getLastASTLocation() const { return LastLoc; }
|
||||
|
||||
|
||||
std::vector<Decl*> &getTopLevelDecls() {
|
||||
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
|
||||
return TopLevelDecls;
|
||||
}
|
||||
const std::vector<Decl*> &getTopLevelDecls() const {
|
||||
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
|
||||
return TopLevelDecls;
|
||||
}
|
||||
|
||||
/// \brief Create a ASTUnit from a PCH file.
|
||||
///
|
||||
/// \param Filename - The PCH file to load.
|
||||
///
|
||||
/// \param DiagClient - The diagnostics client to use. Specify NULL
|
||||
/// to use a default client that emits warnings/errors to standard error.
|
||||
/// The ASTUnit objects takes ownership of this object.
|
||||
///
|
||||
/// \param ErrMsg - Error message to report if the PCH file could not be
|
||||
/// loaded.
|
||||
/// \param Diags - The diagnostics engine to use for reporting errors; its
|
||||
/// lifetime is expected to extend past that of the returned ASTUnit.
|
||||
///
|
||||
/// \returns - The initialized ASTUnit or null if the PCH failed to load.
|
||||
static ASTUnit *LoadFromPCHFile(const std::string &Filename,
|
||||
std::string *ErrMsg = 0,
|
||||
DiagnosticClient *DiagClient = NULL,
|
||||
Diagnostic &Diags,
|
||||
bool OnlyLocalDecls = false,
|
||||
bool UseBumpAllocator = false);
|
||||
|
||||
@ -113,15 +130,35 @@ class ASTUnit {
|
||||
/// \param CI - The compiler invocation to use; it must have exactly one input
|
||||
/// source file.
|
||||
///
|
||||
/// \param Diags - The diagnostics engine to use for reporting errors.
|
||||
/// \param Diags - The diagnostics engine to use for reporting errors; its
|
||||
/// lifetime is expected to extend past that of the returned ASTUnit.
|
||||
//
|
||||
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
|
||||
// shouldn't need to specify them at construction time.
|
||||
static ASTUnit *LoadFromCompilerInvocation(const CompilerInvocation &CI,
|
||||
Diagnostic &Diags,
|
||||
bool OnlyLocalDecls = false,
|
||||
bool UseBumpAllocator = false);
|
||||
bool OnlyLocalDecls = false);
|
||||
|
||||
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
|
||||
/// arguments, which must specify exactly one source file.
|
||||
///
|
||||
/// \param ArgBegin - The beginning of the argument vector.
|
||||
///
|
||||
/// \param ArgEnd - The end of the argument vector.
|
||||
///
|
||||
/// \param Diags - The diagnostics engine to use for reporting errors; its
|
||||
/// lifetime is expected to extend past that of the returned ASTUnit.
|
||||
///
|
||||
/// \param ResourceFilesPath - The path to the compiler resource files.
|
||||
//
|
||||
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
|
||||
// shouldn't need to specify them at construction time.
|
||||
static ASTUnit *LoadFromCommandLine(const char **ArgBegin,
|
||||
const char **ArgEnd,
|
||||
Diagnostic &Diags,
|
||||
llvm::StringRef ResourceFilesPath,
|
||||
bool OnlyLocalDecls = false,
|
||||
bool UseBumpAllocator = false);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
@ -62,6 +62,7 @@ class AnalyzerOptions {
|
||||
std::string AnalyzeSpecificFunction;
|
||||
unsigned AnalyzeAll : 1;
|
||||
unsigned AnalyzerDisplayProgress : 1;
|
||||
unsigned AnalyzeNestedBlocks : 1;
|
||||
unsigned EagerlyAssume : 1;
|
||||
unsigned PurgeDead : 1;
|
||||
unsigned TrimGraph : 1;
|
||||
@ -76,6 +77,7 @@ class AnalyzerOptions {
|
||||
AnalysisDiagOpt = PD_HTML;
|
||||
AnalyzeAll = 0;
|
||||
AnalyzerDisplayProgress = 0;
|
||||
AnalyzeNestedBlocks = 0;
|
||||
EagerlyAssume = 0;
|
||||
PurgeDead = 1;
|
||||
TrimGraph = 0;
|
||||
|
@ -222,7 +222,7 @@ class CompilerInstance {
|
||||
void setDiagnostics(Diagnostic *Value);
|
||||
|
||||
DiagnosticClient &getDiagnosticClient() const {
|
||||
assert(Target && "Compiler instance has no diagnostic client!");
|
||||
assert(DiagClient && "Compiler instance has no diagnostic client!");
|
||||
return *DiagClient;
|
||||
}
|
||||
|
||||
@ -419,9 +419,13 @@ class CompilerInstance {
|
||||
/// logging information.
|
||||
///
|
||||
/// Note that this creates an unowned DiagnosticClient, if using directly the
|
||||
/// caller is responsible for releaseing the returned Diagnostic's client
|
||||
/// caller is responsible for releasing the returned Diagnostic's client
|
||||
/// eventually.
|
||||
///
|
||||
/// \param Opts - The diagnostic options; note that the created text
|
||||
/// diagnostic object contains a reference to these options and its lifetime
|
||||
/// must extend past that of the diagnostic engine.
|
||||
///
|
||||
/// \return The new object on success, or null on failure.
|
||||
static Diagnostic *createDiagnostics(const DiagnosticOptions &Opts,
|
||||
int Argc, char **Argv);
|
||||
@ -482,12 +486,16 @@ class CompilerInstance {
|
||||
|
||||
/// Create the default output file (from the invocation's options) and add it
|
||||
/// to the list of tracked output files.
|
||||
///
|
||||
/// \return - Null on error.
|
||||
llvm::raw_fd_ostream *
|
||||
createDefaultOutputFile(bool Binary = true, llvm::StringRef BaseInput = "",
|
||||
llvm::StringRef Extension = "");
|
||||
|
||||
/// Create a new output file and add it to the list of tracked output files,
|
||||
/// optionally deriving the output path name.
|
||||
///
|
||||
/// \return - Null on error.
|
||||
llvm::raw_fd_ostream *
|
||||
createOutputFile(llvm::StringRef OutputPath, bool Binary = true,
|
||||
llvm::StringRef BaseInput = "",
|
||||
|
@ -82,15 +82,19 @@ class CompilerInvocation {
|
||||
/// \param Res [out] - The resulting invocation.
|
||||
/// \param ArgBegin - The first element in the argument vector.
|
||||
/// \param ArgEnd - The last element in the argument vector.
|
||||
/// \param Diags - The diagnostic engine to use for errors.
|
||||
static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin,
|
||||
const char **ArgEnd, Diagnostic &Diags);
|
||||
|
||||
/// GetBuiltinIncludePath - Get the directory where the compiler headers
|
||||
/// reside, relative to the compiler binary (found by the passed in
|
||||
/// arguments).
|
||||
///
|
||||
/// \param Argv0 - The program path (from argv[0]), for finding the builtin
|
||||
/// compiler path.
|
||||
/// \param MainAddr - The address of main (or some other function in the main
|
||||
/// executable), for finding the builtin compiler path.
|
||||
/// \param Diags - The diagnostic engine to use for errors.
|
||||
static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin,
|
||||
const char **ArgEnd, const char *Argv0,
|
||||
void *MainAddr,
|
||||
Diagnostic &Diags);
|
||||
static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
|
||||
|
||||
/// toArgs - Convert the CompilerInvocation to a list of strings suitable for
|
||||
/// passing to CreateFromArgs.
|
||||
|
@ -77,12 +77,14 @@ class FrontendOptions {
|
||||
unsigned RelocatablePCH : 1; ///< When generating PCH files,
|
||||
/// instruct the PCH writer to create
|
||||
/// relocatable PCH files.
|
||||
unsigned ShowHelp : 1; ///< Show the -help text.
|
||||
unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion
|
||||
/// results.
|
||||
unsigned ShowStats : 1; ///< Show frontend performance
|
||||
/// metrics and statistics.
|
||||
unsigned ShowTimers : 1; ///< Show timers for individual
|
||||
/// actions.
|
||||
unsigned ShowVersion : 1; ///< Show the -version text.
|
||||
|
||||
/// The input files and their types.
|
||||
std::vector<std::pair<InputKind, std::string> > Inputs;
|
||||
@ -105,6 +107,9 @@ class FrontendOptions {
|
||||
/// The name of the action to run when using a plugin action.
|
||||
std::string ActionName;
|
||||
|
||||
/// The list of plugins to load.
|
||||
std::vector<std::string> Plugins;
|
||||
|
||||
public:
|
||||
FrontendOptions() {
|
||||
DebugCodeCompletionPrinter = 1;
|
||||
@ -113,9 +118,11 @@ class FrontendOptions {
|
||||
ProgramAction = frontend::ParseSyntaxOnly;
|
||||
ActionName = "";
|
||||
RelocatablePCH = 0;
|
||||
ShowHelp = 0;
|
||||
ShowMacrosInCodeCompletion = 0;
|
||||
ShowStats = 0;
|
||||
ShowTimers = 0;
|
||||
ShowVersion = 0;
|
||||
}
|
||||
|
||||
/// getInputKindForExtension - Return the appropriate input kind for a file
|
||||
|
@ -61,9 +61,12 @@ class HeaderSearchOptions {
|
||||
std::string CXXEnvIncPath;
|
||||
std::string ObjCXXEnvIncPath;
|
||||
|
||||
/// If non-empty, the path to the compiler builtin include directory, which
|
||||
/// will be searched following the user and environment includes.
|
||||
std::string BuiltinIncludePath;
|
||||
/// The directory which holds the compiler resource files (builtin includes,
|
||||
/// etc.).
|
||||
std::string ResourceDir;
|
||||
|
||||
/// Include the compiler builtin includes.
|
||||
unsigned UseBuiltinIncludes : 1;
|
||||
|
||||
/// Include the system standard include search directories.
|
||||
unsigned UseStandardIncludes : 1;
|
||||
@ -73,7 +76,8 @@ class HeaderSearchOptions {
|
||||
|
||||
public:
|
||||
HeaderSearchOptions(llvm::StringRef _Sysroot = "/")
|
||||
: Sysroot(_Sysroot), UseStandardIncludes(true), Verbose(false) {}
|
||||
: Sysroot(_Sysroot), UseBuiltinIncludes(true),
|
||||
UseStandardIncludes(true), Verbose(false) {}
|
||||
|
||||
/// AddPath - Add the \arg Path path to the specified \arg Group list.
|
||||
void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group,
|
||||
|
@ -404,7 +404,9 @@ namespace clang {
|
||||
/// \brief An ElaboratedType record.
|
||||
TYPE_ELABORATED = 24,
|
||||
/// \brief A SubstTemplateTypeParmType record.
|
||||
TYPE_SUBST_TEMPLATE_TYPE_PARM = 25
|
||||
TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
|
||||
/// \brief An UnresolvedUsingType record.
|
||||
TYPE_UNRESOLVED_USING = 26
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
|
@ -530,7 +530,8 @@ class PCHReader
|
||||
/// \brief Retrieve the name of the original source file name
|
||||
/// directly from the PCH file, without actually loading the PCH
|
||||
/// file.
|
||||
static std::string getOriginalSourceFile(const std::string &PCHFileName);
|
||||
static std::string getOriginalSourceFile(const std::string &PCHFileName,
|
||||
Diagnostic &Diags);
|
||||
|
||||
/// \brief Returns the suggested contents of the predefines buffer,
|
||||
/// which contains a (typically-empty) subset of the predefines
|
||||
@ -552,7 +553,7 @@ class PCHReader
|
||||
const RecordData &Record, unsigned &Idx);
|
||||
|
||||
/// \brief Reads a declarator info from the given record.
|
||||
virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record,
|
||||
virtual TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record,
|
||||
unsigned &Idx);
|
||||
|
||||
/// \brief Resolve a type ID into a type, potentially building a new
|
||||
@ -625,6 +626,9 @@ class PCHReader
|
||||
/// tree.
|
||||
virtual void InitializeSema(Sema &S);
|
||||
|
||||
/// \brief Inform the semantic consumer that Sema is no longer available.
|
||||
virtual void ForgetSema() { SemaObj = 0; }
|
||||
|
||||
/// \brief Retrieve the IdentifierInfo for the named identifier.
|
||||
///
|
||||
/// This routine builds a new IdentifierInfo for the given identifier. If any
|
||||
|
@ -44,7 +44,6 @@ class TargetInfo;
|
||||
/// DenseMap. This uses the standard pointer hash function.
|
||||
struct UnsafeQualTypeDenseMapInfo {
|
||||
static inline bool isEqual(QualType A, QualType B) { return A == B; }
|
||||
static inline bool isPod() { return true; }
|
||||
static inline QualType getEmptyKey() {
|
||||
return QualType::getFromOpaquePtr((void*) 1);
|
||||
}
|
||||
@ -274,7 +273,7 @@ class PCHWriter {
|
||||
void AddTypeRef(QualType T, RecordData &Record);
|
||||
|
||||
/// \brief Emits a reference to a declarator info.
|
||||
void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record);
|
||||
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record);
|
||||
|
||||
/// \brief Emits a template argument location.
|
||||
void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
@ -41,6 +42,21 @@ class PreprocessorOptions {
|
||||
/// If given, a PTH cache file to use for speeding up header parsing.
|
||||
std::string TokenCache;
|
||||
|
||||
/// \brief The set of file remappings, which take existing files on
|
||||
/// the system (the first part of each pair) and gives them the
|
||||
/// contents of other files on the system (the second part of each
|
||||
/// pair).
|
||||
std::vector<std::pair<std::string, std::string> > RemappedFiles;
|
||||
|
||||
typedef std::vector<std::pair<std::string, std::string> >::const_iterator
|
||||
remapped_file_iterator;
|
||||
remapped_file_iterator remapped_file_begin() const {
|
||||
return RemappedFiles.begin();
|
||||
}
|
||||
remapped_file_iterator remapped_file_end() const {
|
||||
return RemappedFiles.end();
|
||||
}
|
||||
|
||||
public:
|
||||
PreprocessorOptions() : UsePredefines(true) {}
|
||||
|
||||
@ -50,6 +66,9 @@ class PreprocessorOptions {
|
||||
void addMacroUndef(llvm::StringRef Name) {
|
||||
Macros.push_back(std::make_pair(Name, true));
|
||||
}
|
||||
void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
|
||||
RemappedFiles.push_back(std::make_pair(From, To));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -134,9 +134,10 @@ struct DenseMapInfo<clang::idx::Entity> {
|
||||
isEqual(clang::idx::Entity LHS, clang::idx::Entity RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
|
||||
static inline bool isPod() { return true; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::idx::Entity> { static const bool value = true; };
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -90,9 +90,10 @@ struct DenseMapInfo<clang::idx::GlobalSelector> {
|
||||
isEqual(clang::idx::GlobalSelector LHS, clang::idx::GlobalSelector RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
|
||||
static inline bool isPod() { return true; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::idx::GlobalSelector> { static const bool value = true;};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -38,8 +38,8 @@ class Lexer : public PreprocessorLexer {
|
||||
const char *BufferEnd; // End of the buffer.
|
||||
SourceLocation FileLoc; // Location for start of file.
|
||||
LangOptions Features; // Features enabled by this language (cache).
|
||||
bool Is_PragmaLexer; // True if lexer for _Pragma handling.
|
||||
bool IsEofCodeCompletion; // True if EOF is treated as a code-completion.
|
||||
bool Is_PragmaLexer : 1; // True if lexer for _Pragma handling.
|
||||
bool IsInConflictMarker : 1; // True if in a VCS conflict marker '<<<<<<<'
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Context-specific lexing flags set by the preprocessor.
|
||||
@ -180,15 +180,6 @@ class Lexer : public PreprocessorLexer {
|
||||
ExtendedTokenMode = Mode ? 1 : 0;
|
||||
}
|
||||
|
||||
/// \brief Specify that end-of-file is to be considered a code-completion
|
||||
/// token.
|
||||
///
|
||||
/// When in this mode, the end-of-file token will be immediately preceded
|
||||
/// by a code-completion token.
|
||||
void SetEofIsCodeCompletion(bool Val = true) {
|
||||
IsEofCodeCompletion = Val;
|
||||
}
|
||||
|
||||
const char *getBufferStart() const { return BufferStart; }
|
||||
|
||||
/// ReadToEndOfLine - Read the rest of the current preprocessor line as an
|
||||
@ -379,6 +370,9 @@ class Lexer : public PreprocessorLexer {
|
||||
bool SkipBCPLComment (Token &Result, const char *CurPtr);
|
||||
bool SkipBlockComment (Token &Result, const char *CurPtr);
|
||||
bool SaveBCPLComment (Token &Result, const char *CurPtr);
|
||||
|
||||
bool IsStartOfConflictMarker(const char *CurPtr);
|
||||
bool HandleEndOfConflictMarker(const char *CurPtr);
|
||||
};
|
||||
|
||||
|
||||
|
@ -91,12 +91,14 @@ class Preprocessor {
|
||||
bool KeepMacroComments : 1;
|
||||
|
||||
// State that changes while the preprocessor runs:
|
||||
bool DisableMacroExpansion : 1; // True if macro expansion is disabled.
|
||||
bool InMacroArgs : 1; // True if parsing fn macro invocation args.
|
||||
|
||||
/// Whether the preprocessor owns the header search object.
|
||||
bool OwnsHeaderSearch : 1;
|
||||
|
||||
/// DisableMacroExpansion - True if macro expansion is disabled.
|
||||
bool DisableMacroExpansion : 1;
|
||||
|
||||
/// Identifiers - This is mapping/lookup information for all identifiers in
|
||||
/// the program, including program keywords.
|
||||
mutable IdentifierTable Identifiers;
|
||||
@ -121,6 +123,9 @@ class Preprocessor {
|
||||
/// with this preprocessor.
|
||||
std::vector<CommentHandler *> CommentHandlers;
|
||||
|
||||
/// \brief The file that we're performing code-completion for, if any.
|
||||
const FileEntry *CodeCompletionFile;
|
||||
|
||||
/// CurLexer - This is the current top of the stack that we're lexing from if
|
||||
/// not expanding a macro and we are lexing directly from source code.
|
||||
/// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
|
||||
@ -134,7 +139,7 @@ class Preprocessor {
|
||||
/// CurPPLexer - This is the current top of the stack what we're lexing from
|
||||
/// if not expanding a macro. This is an alias for either CurLexer or
|
||||
/// CurPTHLexer.
|
||||
PreprocessorLexer* CurPPLexer;
|
||||
PreprocessorLexer *CurPPLexer;
|
||||
|
||||
/// CurLookup - The DirectoryLookup structure used to find the current
|
||||
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
|
||||
@ -171,8 +176,14 @@ class Preprocessor {
|
||||
llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros;
|
||||
|
||||
/// MICache - A "freelist" of MacroInfo objects that can be reused for quick
|
||||
/// allocation.
|
||||
/// allocation.
|
||||
/// FIXME: why not use a singly linked list?
|
||||
std::vector<MacroInfo*> MICache;
|
||||
|
||||
/// MacroArgCache - This is a "freelist" of MacroArg objects that can be
|
||||
/// reused for quick allocation.
|
||||
MacroArgs *MacroArgCache;
|
||||
friend class MacroArgs;
|
||||
|
||||
// Various statistics we track for performance analysis.
|
||||
unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
|
||||
@ -330,8 +341,9 @@ class Preprocessor {
|
||||
|
||||
/// EnterSourceFile - Add a source file to the top of the include stack and
|
||||
/// start lexing tokens from it instead of the current buffer. Return true
|
||||
/// on failure.
|
||||
bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir);
|
||||
/// and fill in ErrorStr with the error information on failure.
|
||||
bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
|
||||
std::string &ErrorStr);
|
||||
|
||||
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
|
||||
/// tokens from it instead of the current buffer. Args specifies the
|
||||
@ -484,6 +496,27 @@ class Preprocessor {
|
||||
CachedTokens[CachedLexPos-1] = Tok;
|
||||
}
|
||||
|
||||
/// \brief Specify the point at which code-completion will be performed.
|
||||
///
|
||||
/// \param File the file in which code completion should occur. If
|
||||
/// this file is included multiple times, code-completion will
|
||||
/// perform completion the first time it is included. If NULL, this
|
||||
/// function clears out the code-completion point.
|
||||
///
|
||||
/// \param Line the line at which code completion should occur
|
||||
/// (1-based).
|
||||
///
|
||||
/// \param Column the column at which code completion should occur
|
||||
/// (1-based).
|
||||
///
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool SetCodeCompletionPoint(const FileEntry *File,
|
||||
unsigned Line, unsigned Column);
|
||||
|
||||
/// \brief Determine if this source location refers into the file
|
||||
/// for which we are performing code completion.
|
||||
bool isCodeCompletionFile(SourceLocation FileLoc) const;
|
||||
|
||||
/// Diag - Forwarding function for diagnostics. This emits a diagnostic at
|
||||
/// the specified Token's location, translating the token's start
|
||||
/// position in the current buffer into a SourcePosition object for rendering.
|
||||
|
@ -334,6 +334,20 @@ class Action : public ActionBase {
|
||||
bool EnteringContext) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// IsInvalidUnlessNestedName - This method is used for error recovery
|
||||
/// purposes to determine whether the specified identifier is only valid as
|
||||
/// a nested name specifier, for example a namespace name. It is
|
||||
/// conservatively correct to always return false from this method.
|
||||
///
|
||||
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
|
||||
virtual bool IsInvalidUnlessNestedName(Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
IdentifierInfo &II,
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
|
||||
/// nested-name-specifier that involves a template-id, e.g.,
|
||||
@ -351,8 +365,19 @@ class Action : public ActionBase {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ShouldEnterDeclaratorScope - Called when a C++ scope specifier
|
||||
/// is parsed as part of a declarator-id to determine whether a scope
|
||||
/// should be entered.
|
||||
///
|
||||
/// \param S the current scope
|
||||
/// \param SS the scope being entered
|
||||
/// \param isFriendDeclaration whether this is a friend declaration
|
||||
virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
|
||||
/// scope or nested-name-specifier) is parsed, part of a declarator-id.
|
||||
/// scope or nested-name-specifier) is parsed as part of a declarator-id.
|
||||
/// After this method is called, according to [C++ 3.4.3p3], names should be
|
||||
/// looked up in the declarator-id's scope, until the declarator is parsed and
|
||||
/// ActOnCXXExitDeclaratorScope is called.
|
||||
@ -1250,6 +1275,10 @@ class Action : public ActionBase {
|
||||
///
|
||||
/// \param AS the currently-active access specifier.
|
||||
///
|
||||
/// \param HasUsingKeyword true if this was declared with an
|
||||
/// explicit 'using' keyword (i.e. if this is technically a using
|
||||
/// declaration, not an access declaration)
|
||||
///
|
||||
/// \param UsingLoc the location of the 'using' keyword.
|
||||
///
|
||||
/// \param SS the nested-name-specifier that precedes the name.
|
||||
@ -1267,6 +1296,7 @@ class Action : public ActionBase {
|
||||
/// \returns a representation of the using declaration.
|
||||
virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
|
||||
AccessSpecifier AS,
|
||||
bool HasUsingKeyword,
|
||||
SourceLocation UsingLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
@ -2394,6 +2424,24 @@ class Action : public ActionBase {
|
||||
/// \param S the scope in which the operator keyword occurs.
|
||||
virtual void CodeCompleteOperatorName(Scope *S) { }
|
||||
|
||||
/// \brief Code completion after the '@' at the top level.
|
||||
///
|
||||
/// \param S the scope in which the '@' occurs.
|
||||
///
|
||||
/// \param ObjCImpDecl the Objective-C implementation or category
|
||||
/// implementation.
|
||||
///
|
||||
/// \param InInterface whether we are in an Objective-C interface or
|
||||
/// protocol.
|
||||
virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
|
||||
bool InInterface) { }
|
||||
|
||||
/// \brief Code completion after the '@' in a statement.
|
||||
virtual void CodeCompleteObjCAtStatement(Scope *S) { }
|
||||
|
||||
/// \brief Code completion after the '@' in an expression.
|
||||
virtual void CodeCompleteObjCAtExpression(Scope *S) { }
|
||||
|
||||
/// \brief Code completion for an ObjC property decl.
|
||||
///
|
||||
/// This code completion action is invoked when the code-completion token is
|
||||
|
@ -27,6 +27,40 @@ namespace clang {
|
||||
class Declarator;
|
||||
struct TemplateIdAnnotation;
|
||||
|
||||
/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope
|
||||
/// specifier.
|
||||
class CXXScopeSpec {
|
||||
SourceRange Range;
|
||||
void *ScopeRep;
|
||||
|
||||
public:
|
||||
CXXScopeSpec() : Range(), ScopeRep() { }
|
||||
|
||||
const SourceRange &getRange() const { return Range; }
|
||||
void setRange(const SourceRange &R) { Range = R; }
|
||||
void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
|
||||
void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
|
||||
SourceLocation getBeginLoc() const { return Range.getBegin(); }
|
||||
SourceLocation getEndLoc() const { return Range.getEnd(); }
|
||||
|
||||
ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; }
|
||||
void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; }
|
||||
|
||||
bool isEmpty() const { return !Range.isValid(); }
|
||||
bool isNotEmpty() const { return !isEmpty(); }
|
||||
|
||||
/// isInvalid - An error occured during parsing of the scope specifier.
|
||||
bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; }
|
||||
|
||||
/// isSet - A scope specifier was resolved to a valid C++ scope.
|
||||
bool isSet() const { return ScopeRep != 0; }
|
||||
|
||||
void clear() {
|
||||
Range = SourceRange();
|
||||
ScopeRep = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// DeclSpec - This class captures information about "declaration specifiers",
|
||||
/// which encompasses storage-class-specifiers, type-specifiers,
|
||||
/// type-qualifiers, and function-specifiers.
|
||||
@ -143,6 +177,9 @@ class DeclSpec {
|
||||
// attributes.
|
||||
AttributeList *AttrList;
|
||||
|
||||
// Scope specifier for the type spec, if applicable.
|
||||
CXXScopeSpec TypeScope;
|
||||
|
||||
// List of protocol qualifiers for objective-c classes. Used for
|
||||
// protocol-qualified interfaces "NString<foo>" and protocol-qualified id
|
||||
// "id<foo>".
|
||||
@ -211,6 +248,8 @@ class DeclSpec {
|
||||
TST getTypeSpecType() const { return (TST)TypeSpecType; }
|
||||
bool isTypeSpecOwned() const { return TypeSpecOwned; }
|
||||
void *getTypeRep() const { return TypeRep; }
|
||||
CXXScopeSpec &getTypeSpecScope() { return TypeScope; }
|
||||
const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
|
||||
|
||||
const SourceRange &getSourceRange() const { return Range; }
|
||||
SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; }
|
||||
@ -436,40 +475,6 @@ class ObjCDeclSpec {
|
||||
IdentifierInfo *SetterName; // setter name of NULL if no setter
|
||||
};
|
||||
|
||||
/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope
|
||||
/// specifier.
|
||||
class CXXScopeSpec {
|
||||
SourceRange Range;
|
||||
void *ScopeRep;
|
||||
|
||||
public:
|
||||
CXXScopeSpec() : Range(), ScopeRep() { }
|
||||
|
||||
const SourceRange &getRange() const { return Range; }
|
||||
void setRange(const SourceRange &R) { Range = R; }
|
||||
void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
|
||||
void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
|
||||
SourceLocation getBeginLoc() const { return Range.getBegin(); }
|
||||
SourceLocation getEndLoc() const { return Range.getEnd(); }
|
||||
|
||||
ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; }
|
||||
void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; }
|
||||
|
||||
bool isEmpty() const { return !Range.isValid(); }
|
||||
bool isNotEmpty() const { return !isEmpty(); }
|
||||
|
||||
/// isInvalid - An error occured during parsing of the scope specifier.
|
||||
bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; }
|
||||
|
||||
/// isSet - A scope specifier was resolved to a valid C++ scope.
|
||||
bool isSet() const { return ScopeRep != 0; }
|
||||
|
||||
void clear() {
|
||||
Range = SourceRange();
|
||||
ScopeRep = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ unqualified-id that has been parsed.
|
||||
class UnqualifiedId {
|
||||
private:
|
||||
|
@ -30,6 +30,7 @@ namespace clang {
|
||||
class DiagnosticBuilder;
|
||||
class Parser;
|
||||
class PragmaUnusedHandler;
|
||||
class ColonProtectionRAIIObject;
|
||||
|
||||
/// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
|
||||
/// an entry is printed for it.
|
||||
@ -47,6 +48,7 @@ class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
|
||||
///
|
||||
class Parser {
|
||||
friend class PragmaUnusedHandler;
|
||||
friend class ColonProtectionRAIIObject;
|
||||
PrettyStackTraceParserEntry CrashInfo;
|
||||
|
||||
Preprocessor &PP;
|
||||
@ -90,26 +92,16 @@ class Parser {
|
||||
/// template argument list, where the '>' closes the template
|
||||
/// argument list.
|
||||
bool GreaterThanIsOperator;
|
||||
|
||||
/// ColonIsSacred - When this is false, we aggressively try to recover from
|
||||
/// code like "foo : bar" as if it were a typo for "foo :: bar". This is not
|
||||
/// safe in case statements and a few other things. This is managed by the
|
||||
/// ColonProtectionRAIIObject RAII object.
|
||||
bool ColonIsSacred;
|
||||
|
||||
/// The "depth" of the template parameters currently being parsed.
|
||||
unsigned TemplateParameterDepth;
|
||||
|
||||
/// \brief RAII object that makes '>' behave either as an operator
|
||||
/// or as the closing angle bracket for a template argument list.
|
||||
struct GreaterThanIsOperatorScope {
|
||||
bool &GreaterThanIsOperator;
|
||||
bool OldGreaterThanIsOperator;
|
||||
|
||||
GreaterThanIsOperatorScope(bool >IO, bool Val)
|
||||
: GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
|
||||
GreaterThanIsOperator = Val;
|
||||
}
|
||||
|
||||
~GreaterThanIsOperatorScope() {
|
||||
GreaterThanIsOperator = OldGreaterThanIsOperator;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Parser(Preprocessor &PP, Action &Actions);
|
||||
~Parser();
|
||||
@ -759,7 +751,10 @@ class Parser {
|
||||
bool isStartOfFunctionDefinition();
|
||||
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
|
||||
AccessSpecifier AS = AS_none);
|
||||
|
||||
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
|
||||
AttributeList *Attr,
|
||||
AccessSpecifier AS = AS_none);
|
||||
|
||||
DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
|
||||
void ParseKNRParamDeclarations(Declarator &D);
|
||||
@ -1087,6 +1082,7 @@ class Parser {
|
||||
private:
|
||||
virtual void _anchor();
|
||||
};
|
||||
struct ObjCPropertyCallback;
|
||||
|
||||
void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
|
||||
|
||||
@ -1288,7 +1284,7 @@ class Parser {
|
||||
tok::TokenKind *After = 0);
|
||||
|
||||
DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
|
||||
DeclPtrTy ParseLinkage(unsigned Context);
|
||||
DeclPtrTy ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
|
||||
DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context,
|
||||
SourceLocation &DeclEnd,
|
||||
CXX0XAttributeList Attrs);
|
||||
|
@ -34,6 +34,9 @@ class ExternalSemaSource : public ExternalASTSource {
|
||||
/// tree.
|
||||
virtual void InitializeSema(Sema &S) {}
|
||||
|
||||
/// \brief Inform the semantic consumer that Sema is no longer available.
|
||||
virtual void ForgetSema() {}
|
||||
|
||||
/// \brief Load the contents of the global method pool for a given
|
||||
/// selector.
|
||||
///
|
||||
|
@ -34,6 +34,9 @@ namespace clang {
|
||||
/// tree.
|
||||
virtual void InitializeSema(Sema &S) {}
|
||||
|
||||
/// \brief Inform the semantic consumer that Sema is no longer available.
|
||||
virtual void ForgetSema() {}
|
||||
|
||||
// isa/cast/dyn_cast support
|
||||
static bool classof(const ASTConsumer *Consumer) {
|
||||
return Consumer->SemaConsumer;
|
||||
|
@ -260,24 +260,40 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
|
||||
}
|
||||
|
||||
NamedDecl *
|
||||
ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
|
||||
ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
|
||||
llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
|
||||
= InstantiatedFromUnresolvedUsingDecl.find(UUD);
|
||||
if (Pos == InstantiatedFromUnresolvedUsingDecl.end())
|
||||
= InstantiatedFromUsingDecl.find(UUD);
|
||||
if (Pos == InstantiatedFromUsingDecl.end())
|
||||
return 0;
|
||||
|
||||
return Pos->second;
|
||||
}
|
||||
|
||||
void
|
||||
ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD,
|
||||
NamedDecl *UUD) {
|
||||
assert((isa<UnresolvedUsingValueDecl>(UUD) ||
|
||||
isa<UnresolvedUsingTypenameDecl>(UUD)) &&
|
||||
"original declaration is not an unresolved using decl");
|
||||
assert(!InstantiatedFromUnresolvedUsingDecl[UD] &&
|
||||
"Already noted what using decl what instantiated from");
|
||||
InstantiatedFromUnresolvedUsingDecl[UD] = UUD;
|
||||
ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
|
||||
assert((isa<UsingDecl>(Pattern) ||
|
||||
isa<UnresolvedUsingValueDecl>(Pattern) ||
|
||||
isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
|
||||
"pattern decl is not a using decl");
|
||||
assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
|
||||
InstantiatedFromUsingDecl[Inst] = Pattern;
|
||||
}
|
||||
|
||||
UsingShadowDecl *
|
||||
ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) {
|
||||
llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
|
||||
= InstantiatedFromUsingShadowDecl.find(Inst);
|
||||
if (Pos == InstantiatedFromUsingShadowDecl.end())
|
||||
return 0;
|
||||
|
||||
return Pos->second;
|
||||
}
|
||||
|
||||
void
|
||||
ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
|
||||
UsingShadowDecl *Pattern) {
|
||||
assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists");
|
||||
InstantiatedFromUsingShadowDecl[Inst] = Pattern;
|
||||
}
|
||||
|
||||
FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) {
|
||||
@ -711,10 +727,6 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||
break;
|
||||
}
|
||||
case Type::MemberPointer: {
|
||||
// FIXME: This is ABI dependent. We use the Itanium C++ ABI.
|
||||
// http://www.codesourcery.com/public/cxx-abi/abi.html#member-pointers
|
||||
// If we ever want to support other ABIs this needs to be abstracted.
|
||||
|
||||
QualType Pointee = cast<MemberPointerType>(T)->getPointeeType();
|
||||
std::pair<uint64_t, unsigned> PtrDiffInfo =
|
||||
getTypeInfo(getPointerDiffType());
|
||||
@ -997,31 +1009,31 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
|
||||
ObjCImpls[CatD] = ImplD;
|
||||
}
|
||||
|
||||
/// \brief Allocate an uninitialized DeclaratorInfo.
|
||||
/// \brief Allocate an uninitialized TypeSourceInfo.
|
||||
///
|
||||
/// The caller should initialize the memory held by DeclaratorInfo using
|
||||
/// The caller should initialize the memory held by TypeSourceInfo using
|
||||
/// the TypeLoc wrappers.
|
||||
///
|
||||
/// \param T the type that will be the basis for type source info. This type
|
||||
/// should refer to how the declarator was written in source code, not to
|
||||
/// what type semantic analysis resolved the declarator to.
|
||||
DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T,
|
||||
TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T,
|
||||
unsigned DataSize) {
|
||||
if (!DataSize)
|
||||
DataSize = TypeLoc::getFullDataSizeForType(T);
|
||||
else
|
||||
assert(DataSize == TypeLoc::getFullDataSizeForType(T) &&
|
||||
"incorrect data size provided to CreateDeclaratorInfo!");
|
||||
"incorrect data size provided to CreateTypeSourceInfo!");
|
||||
|
||||
DeclaratorInfo *DInfo =
|
||||
(DeclaratorInfo*)BumpAlloc.Allocate(sizeof(DeclaratorInfo) + DataSize, 8);
|
||||
new (DInfo) DeclaratorInfo(T);
|
||||
return DInfo;
|
||||
TypeSourceInfo *TInfo =
|
||||
(TypeSourceInfo*)BumpAlloc.Allocate(sizeof(TypeSourceInfo) + DataSize, 8);
|
||||
new (TInfo) TypeSourceInfo(T);
|
||||
return TInfo;
|
||||
}
|
||||
|
||||
DeclaratorInfo *ASTContext::getTrivialDeclaratorInfo(QualType T,
|
||||
TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T,
|
||||
SourceLocation L) {
|
||||
DeclaratorInfo *DI = CreateDeclaratorInfo(T);
|
||||
TypeSourceInfo *DI = CreateTypeSourceInfo(T);
|
||||
DI->getTypeLoc().initialize(L);
|
||||
return DI;
|
||||
}
|
||||
@ -1092,6 +1104,20 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
|
||||
return *NewEntry;
|
||||
}
|
||||
|
||||
const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
|
||||
RD = cast<CXXRecordDecl>(RD->getDefinition(*this));
|
||||
assert(RD && "Cannot get key function for forward declarations!");
|
||||
|
||||
const CXXMethodDecl *&Entry = KeyFunctions[RD];
|
||||
if (!Entry)
|
||||
Entry = ASTRecordLayoutBuilder::ComputeKeyFunction(RD);
|
||||
else
|
||||
assert(Entry == ASTRecordLayoutBuilder::ComputeKeyFunction(RD) &&
|
||||
"Key function changed!");
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type creation/memoization methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1174,32 +1200,42 @@ QualType ASTContext::getObjCGCQualType(QualType T,
|
||||
return getExtQualType(TypeNode, Quals);
|
||||
}
|
||||
|
||||
QualType ASTContext::getNoReturnType(QualType T) {
|
||||
QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
|
||||
QualType ResultType;
|
||||
if (T->isPointerType()) {
|
||||
QualType Pointee = T->getAs<PointerType>()->getPointeeType();
|
||||
ResultType = getNoReturnType(Pointee);
|
||||
if (const PointerType *Pointer = T->getAs<PointerType>()) {
|
||||
QualType Pointee = Pointer->getPointeeType();
|
||||
ResultType = getNoReturnType(Pointee, AddNoReturn);
|
||||
if (ResultType == Pointee)
|
||||
return T;
|
||||
|
||||
ResultType = getPointerType(ResultType);
|
||||
} else if (T->isBlockPointerType()) {
|
||||
QualType Pointee = T->getAs<BlockPointerType>()->getPointeeType();
|
||||
ResultType = getNoReturnType(Pointee);
|
||||
} else if (const BlockPointerType *BlockPointer
|
||||
= T->getAs<BlockPointerType>()) {
|
||||
QualType Pointee = BlockPointer->getPointeeType();
|
||||
ResultType = getNoReturnType(Pointee, AddNoReturn);
|
||||
if (ResultType == Pointee)
|
||||
return T;
|
||||
|
||||
ResultType = getBlockPointerType(ResultType);
|
||||
} else {
|
||||
assert (T->isFunctionType()
|
||||
&& "can't noreturn qualify non-pointer to function or block type");
|
||||
|
||||
if (const FunctionNoProtoType *FNPT = T->getAs<FunctionNoProtoType>()) {
|
||||
ResultType = getFunctionNoProtoType(FNPT->getResultType(), true);
|
||||
} else if (const FunctionType *F = T->getAs<FunctionType>()) {
|
||||
if (F->getNoReturnAttr() == AddNoReturn)
|
||||
return T;
|
||||
|
||||
if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
|
||||
ResultType = getFunctionNoProtoType(FNPT->getResultType(), AddNoReturn);
|
||||
} else {
|
||||
const FunctionProtoType *F = T->getAs<FunctionProtoType>();
|
||||
const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
|
||||
ResultType
|
||||
= getFunctionType(F->getResultType(), F->arg_type_begin(),
|
||||
F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
|
||||
F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
|
||||
F->getNumExceptions(), F->exception_begin(), true);
|
||||
= getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
|
||||
FPT->getNumArgs(), FPT->isVariadic(),
|
||||
FPT->getTypeQuals(),
|
||||
FPT->hasExceptionSpec(), FPT->hasAnyExceptionSpec(),
|
||||
FPT->getNumExceptions(), FPT->exception_begin(),
|
||||
AddNoReturn);
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
return T;
|
||||
|
||||
return getQualifiedType(ResultType, T.getLocalQualifiers());
|
||||
}
|
||||
|
||||
@ -1766,6 +1802,9 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) {
|
||||
Decl->TypeForDecl = PrevDecl->TypeForDecl;
|
||||
else
|
||||
Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum);
|
||||
} else if (UnresolvedUsingTypenameDecl *Using =
|
||||
dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
|
||||
Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using);
|
||||
} else
|
||||
assert(false && "TypeDecl without a type?");
|
||||
|
||||
@ -2238,7 +2277,7 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) {
|
||||
/// getSizeType - Return the unique type for "size_t" (C99 7.17), the result
|
||||
/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
|
||||
/// needs to agree with the definition in <stddef.h>.
|
||||
QualType ASTContext::getSizeType() const {
|
||||
CanQualType ASTContext::getSizeType() const {
|
||||
return getFromTargetType(Target.getSizeType());
|
||||
}
|
||||
|
||||
@ -2354,8 +2393,9 @@ DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
|
||||
}
|
||||
}
|
||||
|
||||
assert(Name.getAsOverloadedFunctionDecl());
|
||||
return Name.getAsOverloadedFunctionDecl()->getDeclName();
|
||||
OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
|
||||
assert(Storage);
|
||||
return (*Storage->begin())->getDeclName();
|
||||
}
|
||||
|
||||
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
|
||||
@ -2364,27 +2404,7 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
|
||||
if (TemplateDecl *Template = Name.getAsTemplateDecl())
|
||||
return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
|
||||
|
||||
// If this template name refers to a set of overloaded function templates,
|
||||
/// the canonical template name merely stores the set of function templates.
|
||||
if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) {
|
||||
OverloadedFunctionDecl *CanonOvl = 0;
|
||||
for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
|
||||
FEnd = Ovl->function_end();
|
||||
F != FEnd; ++F) {
|
||||
Decl *Canon = F->get()->getCanonicalDecl();
|
||||
if (CanonOvl || Canon != F->get()) {
|
||||
if (!CanonOvl)
|
||||
CanonOvl = OverloadedFunctionDecl::Create(*this,
|
||||
Ovl->getDeclContext(),
|
||||
Ovl->getDeclName());
|
||||
|
||||
CanonOvl->addOverload(
|
||||
AnyFunctionDecl::getFromNamedDecl(cast<NamedDecl>(Canon)));
|
||||
}
|
||||
}
|
||||
|
||||
return TemplateName(CanonOvl? CanonOvl : Ovl);
|
||||
}
|
||||
assert(!Name.getAsOverloadedTemplate());
|
||||
|
||||
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
|
||||
assert(DTN && "Non-dependent template names must refer to template decls.");
|
||||
@ -2651,7 +2671,7 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) {
|
||||
unsigned ASTContext::getIntegerRank(Type *T) {
|
||||
assert(T->isCanonicalUnqualified() && "T should be canonicalized");
|
||||
if (EnumType* ET = dyn_cast<EnumType>(T))
|
||||
T = ET->getDecl()->getIntegerType().getTypePtr();
|
||||
T = ET->getDecl()->getPromotionType().getTypePtr();
|
||||
|
||||
if (T->isSpecificBuiltinType(BuiltinType::WChar))
|
||||
T = getFromTargetType(Target.getWCharType()).getTypePtr();
|
||||
@ -2732,6 +2752,8 @@ QualType ASTContext::isPromotableBitField(Expr *E) {
|
||||
QualType ASTContext::getPromotedIntegerType(QualType Promotable) {
|
||||
assert(!Promotable.isNull());
|
||||
assert(Promotable->isPromotableIntegerType());
|
||||
if (const EnumType *ET = Promotable->getAs<EnumType>())
|
||||
return ET->getDecl()->getPromotionType();
|
||||
if (Promotable->isSignedIntegerType())
|
||||
return IntTy;
|
||||
uint64_t PromotableSize = getTypeSize(Promotable);
|
||||
@ -2812,7 +2834,7 @@ QualType ASTContext::getCFConstantStringType() {
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl,
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
CFConstantStringTypeDecl->addDecl(Field);
|
||||
@ -2848,7 +2870,7 @@ QualType ASTContext::getObjCFastEnumerationStateType() {
|
||||
FieldDecl *Field = FieldDecl::Create(*this,
|
||||
ObjCFastEnumerationStateTypeDecl,
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
ObjCFastEnumerationStateTypeDecl->addDecl(Field);
|
||||
@ -2884,7 +2906,7 @@ QualType ASTContext::getBlockDescriptorType() {
|
||||
T,
|
||||
SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
@ -2931,7 +2953,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() {
|
||||
T,
|
||||
SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
@ -3009,7 +3031,7 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
|
||||
continue;
|
||||
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0, /*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
@ -3052,7 +3074,7 @@ QualType ASTContext::getBlockParmType(
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0, /*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
@ -3072,7 +3094,7 @@ QualType ASTContext::getBlockParmType(
|
||||
FieldType);
|
||||
|
||||
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
||||
Name, FieldType, /*DInfo=*/0,
|
||||
Name, FieldType, /*TInfo=*/0,
|
||||
/*BitWidth=*/0, /*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
@ -3690,6 +3712,29 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
|
||||
ObjCConstantStringType = getObjCInterfaceType(Decl);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template name that corresponds to a non-empty
|
||||
/// lookup.
|
||||
TemplateName ASTContext::getOverloadedTemplateName(NamedDecl * const *Begin,
|
||||
NamedDecl * const *End) {
|
||||
unsigned size = End - Begin;
|
||||
assert(size > 1 && "set is not overloaded!");
|
||||
|
||||
void *memory = Allocate(sizeof(OverloadedTemplateStorage) +
|
||||
size * sizeof(FunctionTemplateDecl*));
|
||||
OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size);
|
||||
|
||||
NamedDecl **Storage = OT->getStorage();
|
||||
for (NamedDecl * const *I = Begin; I != End; ++I) {
|
||||
NamedDecl *D = *I;
|
||||
assert(isa<FunctionTemplateDecl>(D) ||
|
||||
(isa<UsingShadowDecl>(D) &&
|
||||
isa<FunctionTemplateDecl>(D->getUnderlyingDecl())));
|
||||
*Storage++ = D;
|
||||
}
|
||||
|
||||
return TemplateName(OT);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template name that represents a qualified
|
||||
/// template name such as \c std::vector.
|
||||
TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
@ -3709,25 +3754,6 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
return TemplateName(QTN);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template name that represents a qualified
|
||||
/// template name such as \c std::vector.
|
||||
TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
OverloadedFunctionDecl *Template) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
|
||||
|
||||
void *InsertPos = 0;
|
||||
QualifiedTemplateName *QTN =
|
||||
QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
||||
if (!QTN) {
|
||||
QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template);
|
||||
QualifiedTemplateNames.InsertNode(QTN, InsertPos);
|
||||
}
|
||||
|
||||
return TemplateName(QTN);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template name that represents a dependent
|
||||
/// template name such as \c MetaFun::template apply.
|
||||
TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
@ -4334,6 +4360,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
|
||||
if (LHSClass != RHSClass) {
|
||||
// C99 6.7.2.2p4: Each enumerated type shall be compatible with char,
|
||||
// a signed integer type, or an unsigned integer type.
|
||||
// Compatibility is based on the underlying type, not the promotion
|
||||
// type.
|
||||
if (const EnumType* ETy = LHS->getAs<EnumType>()) {
|
||||
if (ETy->getDecl()->getIntegerType() == RHSCan.getUnqualifiedType())
|
||||
return RHS;
|
||||
@ -4493,6 +4521,8 @@ unsigned ASTContext::getIntWidth(QualType T) {
|
||||
if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
|
||||
return FWIT->getWidth();
|
||||
}
|
||||
if (EnumType *ET = dyn_cast<EnumType>(T))
|
||||
T = ET->getDecl()->getIntegerType();
|
||||
// For builtin types, just use the standard type sizing method
|
||||
return (unsigned)getTypeSize(T);
|
||||
}
|
||||
|
@ -90,6 +90,57 @@ bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) cons
|
||||
return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths);
|
||||
}
|
||||
|
||||
static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) {
|
||||
// OpaqueTarget is a CXXRecordDecl*.
|
||||
return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget;
|
||||
}
|
||||
|
||||
bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const {
|
||||
return forallBases(BaseIsNot, (void*) Base->getCanonicalDecl());
|
||||
}
|
||||
|
||||
bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
|
||||
void *OpaqueData,
|
||||
bool AllowShortCircuit) const {
|
||||
ASTContext &Context = getASTContext();
|
||||
llvm::SmallVector<const CXXRecordDecl*, 8> Queue;
|
||||
|
||||
const CXXRecordDecl *Record = this;
|
||||
bool AllMatches = true;
|
||||
while (true) {
|
||||
for (CXXRecordDecl::base_class_const_iterator
|
||||
I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) {
|
||||
const RecordType *Ty = I->getType()->getAs<RecordType>();
|
||||
if (!Ty) {
|
||||
if (AllowShortCircuit) return false;
|
||||
AllMatches = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
CXXRecordDecl *Base =
|
||||
cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition(Context));
|
||||
if (!Base) {
|
||||
if (AllowShortCircuit) return false;
|
||||
AllMatches = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
Queue.push_back(Base);
|
||||
if (!BaseMatches(Base, OpaqueData)) {
|
||||
if (AllowShortCircuit) return false;
|
||||
AllMatches = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (Queue.empty()) break;
|
||||
Record = Queue.back(); // not actually a queue.
|
||||
Queue.pop_back();
|
||||
}
|
||||
|
||||
return AllMatches;
|
||||
}
|
||||
|
||||
bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
|
||||
void *UserData,
|
||||
CXXBasePaths &Paths) const {
|
||||
|
@ -38,7 +38,7 @@ void Attr::Destroy(ASTContext &C) {
|
||||
}
|
||||
|
||||
/// \brief Return the TypeLoc wrapper for the type source info.
|
||||
TypeLoc DeclaratorInfo::getTypeLoc() const {
|
||||
TypeLoc TypeSourceInfo::getTypeLoc() const {
|
||||
return TypeLoc(Ty, (void*)(this + 1));
|
||||
}
|
||||
|
||||
@ -86,17 +86,17 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
|
||||
|
||||
ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, Expr *DefArg) {
|
||||
return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, DInfo, S, DefArg);
|
||||
return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, TInfo, S, DefArg);
|
||||
}
|
||||
|
||||
SourceRange ParmVarDecl::getDefaultArgRange() const {
|
||||
if (const Expr *E = getInit())
|
||||
return E->getSourceRange();
|
||||
|
||||
if (const Expr *E = getUninstantiatedDefaultArg())
|
||||
return E->getSourceRange();
|
||||
if (hasUninstantiatedDefaultArg())
|
||||
return getUninstantiatedDefaultArg()->getSourceRange();
|
||||
|
||||
return SourceRange();
|
||||
}
|
||||
@ -136,11 +136,11 @@ bool VarDecl::isExternC() const {
|
||||
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
DeclarationName N, QualType T,
|
||||
DeclaratorInfo *DInfo,
|
||||
TypeSourceInfo *TInfo,
|
||||
StorageClass S, bool isInline,
|
||||
bool hasWrittenPrototype) {
|
||||
FunctionDecl *New
|
||||
= new (C) FunctionDecl(Function, DC, L, N, T, DInfo, S, isInline);
|
||||
= new (C) FunctionDecl(Function, DC, L, N, T, TInfo, S, isInline);
|
||||
New->HasWrittenPrototype = hasWrittenPrototype;
|
||||
return New;
|
||||
}
|
||||
@ -151,8 +151,8 @@ BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
||||
|
||||
FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
DeclaratorInfo *DInfo, Expr *BW, bool Mutable) {
|
||||
return new (C) FieldDecl(Decl::Field, DC, L, Id, T, DInfo, BW, Mutable);
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable) {
|
||||
return new (C) FieldDecl(Decl::Field, DC, L, Id, T, TInfo, BW, Mutable);
|
||||
}
|
||||
|
||||
bool FieldDecl::isAnonymousStructOrUnion() const {
|
||||
@ -179,8 +179,8 @@ void EnumConstantDecl::Destroy(ASTContext& C) {
|
||||
|
||||
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
DeclaratorInfo *DInfo) {
|
||||
return new (C) TypedefDecl(DC, L, Id, DInfo);
|
||||
TypeSourceInfo *TInfo) {
|
||||
return new (C) TypedefDecl(DC, L, Id, TInfo);
|
||||
}
|
||||
|
||||
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
@ -195,9 +195,12 @@ void EnumDecl::Destroy(ASTContext& C) {
|
||||
Decl::Destroy(C);
|
||||
}
|
||||
|
||||
void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {
|
||||
void EnumDecl::completeDefinition(ASTContext &C,
|
||||
QualType NewType,
|
||||
QualType NewPromotionType) {
|
||||
assert(!isDefinition() && "Cannot redefine enums!");
|
||||
IntegerType = NewType;
|
||||
PromotionType = NewPromotionType;
|
||||
TagDecl::completeDefinition();
|
||||
}
|
||||
|
||||
@ -535,9 +538,9 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo,
|
||||
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S) {
|
||||
return new (C) VarDecl(Var, DC, L, Id, T, DInfo, S);
|
||||
return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S);
|
||||
}
|
||||
|
||||
void VarDecl::Destroy(ASTContext& C) {
|
||||
@ -838,8 +841,20 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
|
||||
}
|
||||
|
||||
bool FunctionDecl::isInlined() const {
|
||||
if (isInlineSpecified() || (isa<CXXMethodDecl>(this) && !isOutOfLine()))
|
||||
// FIXME: This is not enough. Consider:
|
||||
//
|
||||
// inline void f();
|
||||
// void f() { }
|
||||
//
|
||||
// f is inlined, but does not have inline specified.
|
||||
// To fix this we should add an 'inline' flag to FunctionDecl.
|
||||
if (isInlineSpecified())
|
||||
return true;
|
||||
|
||||
if (isa<CXXMethodDecl>(this)) {
|
||||
if (!isOutOfLine() || getCanonicalDecl()->isInlineSpecified())
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
@ -1199,7 +1214,7 @@ TagDecl* TagDecl::getDefinition(ASTContext& C) const {
|
||||
|
||||
TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) {
|
||||
switch (TypeSpec) {
|
||||
default: llvm::llvm_unreachable("unexpected type specifier");
|
||||
default: llvm_unreachable("unexpected type specifier");
|
||||
case DeclSpec::TST_struct: return TK_struct;
|
||||
case DeclSpec::TST_class: return TK_class;
|
||||
case DeclSpec::TST_union: return TK_union;
|
||||
|
@ -190,7 +190,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case CXXConstructor:
|
||||
case CXXDestructor:
|
||||
case CXXConversion:
|
||||
case OverloadedFunction:
|
||||
case Typedef:
|
||||
case EnumConstant:
|
||||
case Var:
|
||||
@ -199,7 +198,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case NonTypeTemplateParm:
|
||||
case ObjCMethod:
|
||||
case ObjCContainer:
|
||||
case ObjCCategory:
|
||||
case ObjCInterface:
|
||||
case ObjCProperty:
|
||||
case ObjCCompatibleAlias:
|
||||
@ -221,8 +219,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case ObjCImplementation:
|
||||
return IDNS_ObjCImplementation;
|
||||
|
||||
case ObjCCategory:
|
||||
case ObjCCategoryImpl:
|
||||
return IDNS_ObjCCategoryImpl;
|
||||
return IDNS_ObjCCategoryName;
|
||||
|
||||
case Field:
|
||||
case ObjCAtDefsField:
|
||||
@ -637,6 +636,46 @@ bool DeclContext::decls_empty() const {
|
||||
return !FirstDecl;
|
||||
}
|
||||
|
||||
void DeclContext::removeDecl(Decl *D) {
|
||||
assert(D->getLexicalDeclContext() == this &&
|
||||
"decl being removed from non-lexical context");
|
||||
assert((D->NextDeclInContext || D == LastDecl) &&
|
||||
"decl is not in decls list");
|
||||
|
||||
// Remove D from the decl chain. This is O(n) but hopefully rare.
|
||||
if (D == FirstDecl) {
|
||||
if (D == LastDecl)
|
||||
FirstDecl = LastDecl = 0;
|
||||
else
|
||||
FirstDecl = D->NextDeclInContext;
|
||||
} else {
|
||||
for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) {
|
||||
assert(I && "decl not found in linked list");
|
||||
if (I->NextDeclInContext == D) {
|
||||
I->NextDeclInContext = D->NextDeclInContext;
|
||||
if (D == LastDecl) LastDecl = I;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mark that D is no longer in the decl chain.
|
||||
D->NextDeclInContext = 0;
|
||||
|
||||
// Remove D from the lookup table if necessary.
|
||||
if (isa<NamedDecl>(D)) {
|
||||
NamedDecl *ND = cast<NamedDecl>(D);
|
||||
|
||||
void *OpaqueMap = getPrimaryContext()->LookupPtr;
|
||||
if (!OpaqueMap) return;
|
||||
|
||||
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(OpaqueMap);
|
||||
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
|
||||
assert(Pos != Map->end() && "no lookup entry for decl");
|
||||
Pos->second.remove(ND);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclContext::addHiddenDecl(Decl *D) {
|
||||
assert(D->getLexicalDeclContext() == this &&
|
||||
"Decl inserted into wrong lexical context");
|
||||
@ -742,6 +781,9 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
|
||||
// from being visible?
|
||||
if (isa<ClassTemplateSpecializationDecl>(D))
|
||||
return;
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
if (FD->isFunctionTemplateSpecialization())
|
||||
return;
|
||||
|
||||
DeclContext *PrimaryContext = getPrimaryContext();
|
||||
if (PrimaryContext != this) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
@ -438,6 +439,18 @@ void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
|
||||
Conversions.addDecl(ConvDecl);
|
||||
}
|
||||
|
||||
|
||||
void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) {
|
||||
Method->setVirtualAsWritten(true);
|
||||
setAggregate(false);
|
||||
setPOD(false);
|
||||
setEmpty(false);
|
||||
setPolymorphic(true);
|
||||
setHasTrivialConstructor(false);
|
||||
setHasTrivialCopyConstructor(false);
|
||||
setHasTrivialCopyAssignment(false);
|
||||
}
|
||||
|
||||
CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
|
||||
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
|
||||
return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
|
||||
@ -459,8 +472,8 @@ CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
|
||||
= new (getASTContext()) MemberSpecializationInfo(RD, TSK);
|
||||
}
|
||||
|
||||
TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() {
|
||||
if (ClassTemplateSpecializationDecl *Spec
|
||||
TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
|
||||
if (const ClassTemplateSpecializationDecl *Spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(this))
|
||||
return Spec->getSpecializationKind();
|
||||
|
||||
@ -507,8 +520,7 @@ CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CXXDestructorDecl *
|
||||
CXXRecordDecl::getDestructor(ASTContext &Context) {
|
||||
CXXDestructorDecl *CXXRecordDecl::getDestructor(ASTContext &Context) {
|
||||
QualType ClassType = Context.getTypeDeclType(this);
|
||||
|
||||
DeclarationName Name
|
||||
@ -519,7 +531,7 @@ CXXRecordDecl::getDestructor(ASTContext &Context) {
|
||||
llvm::tie(I, E) = lookup(Name);
|
||||
assert(I != E && "Did not find a destructor!");
|
||||
|
||||
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
|
||||
CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
|
||||
assert(++I == E && "Found more than one destructor!");
|
||||
|
||||
return Dtor;
|
||||
@ -528,9 +540,9 @@ CXXRecordDecl::getDestructor(ASTContext &Context) {
|
||||
CXXMethodDecl *
|
||||
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isStatic, bool isInline) {
|
||||
return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, DInfo,
|
||||
return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, TInfo,
|
||||
isStatic, isInline);
|
||||
}
|
||||
|
||||
@ -577,6 +589,8 @@ typedef llvm::DenseMap<const CXXMethodDecl*,
|
||||
static OverriddenMethodsMapTy *OverriddenMethods = 0;
|
||||
|
||||
void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
|
||||
assert(MD->isCanonicalDecl() && "Method is not canonical!");
|
||||
|
||||
// FIXME: The CXXMethodDecl dtor needs to remove and free the entry.
|
||||
|
||||
if (!OverriddenMethods)
|
||||
@ -630,55 +644,107 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
|
||||
return C.getPointerType(ClassTy);
|
||||
}
|
||||
|
||||
CXXBaseOrMemberInitializer::
|
||||
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs,
|
||||
CXXConstructorDecl *C,
|
||||
SourceLocation L, SourceLocation R)
|
||||
: Args(0), NumArgs(0), CtorOrAnonUnion(), IdLoc(L), RParenLoc(R) {
|
||||
BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
|
||||
assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
|
||||
BaseOrMember |= 0x01;
|
||||
static bool MethodHasBody(const CXXMethodDecl *MD, const FunctionDecl *&fn) {
|
||||
// Simple case: function has a body
|
||||
if (MD->getBody(fn))
|
||||
return true;
|
||||
|
||||
if (NumArgs > 0) {
|
||||
this->NumArgs = NumArgs;
|
||||
// FIXME. Allocation via Context
|
||||
this->Args = new Stmt*[NumArgs];
|
||||
for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
|
||||
this->Args[Idx] = Args[Idx];
|
||||
}
|
||||
CtorOrAnonUnion = C;
|
||||
// Complex case: function is an instantiation of a function which has a
|
||||
// body, but the definition hasn't been instantiated.
|
||||
const FunctionDecl *PatternDecl = MD->getTemplateInstantiationPattern();
|
||||
if (PatternDecl && PatternDecl->getBody(fn))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CXXMethodDecl::hasInlineBody() const {
|
||||
const FunctionDecl *fn;
|
||||
return MethodHasBody(this, fn) && !fn->isOutOfLine();
|
||||
}
|
||||
|
||||
CXXBaseOrMemberInitializer::
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs,
|
||||
CXXConstructorDecl *C,
|
||||
SourceLocation L, SourceLocation R)
|
||||
: Args(0), NumArgs(0), CtorOrAnonUnion(), IdLoc(L), RParenLoc(R) {
|
||||
BaseOrMember = reinterpret_cast<uintptr_t>(Member);
|
||||
assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
|
||||
|
||||
CXXBaseOrMemberInitializer(ASTContext &Context,
|
||||
TypeSourceInfo *TInfo, CXXConstructorDecl *C,
|
||||
SourceLocation L,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
SourceLocation R)
|
||||
: BaseOrMember(TInfo), Args(0), NumArgs(0), CtorOrAnonUnion(C),
|
||||
LParenLoc(L), RParenLoc(R)
|
||||
{
|
||||
if (NumArgs > 0) {
|
||||
this->NumArgs = NumArgs;
|
||||
this->Args = new Stmt*[NumArgs];
|
||||
this->Args = new (Context) Stmt*[NumArgs];
|
||||
for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
|
||||
this->Args[Idx] = Args[Idx];
|
||||
}
|
||||
CtorOrAnonUnion = C;
|
||||
}
|
||||
|
||||
CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
|
||||
delete [] Args;
|
||||
CXXBaseOrMemberInitializer::
|
||||
CXXBaseOrMemberInitializer(ASTContext &Context,
|
||||
FieldDecl *Member, SourceLocation MemberLoc,
|
||||
CXXConstructorDecl *C, SourceLocation L,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
SourceLocation R)
|
||||
: BaseOrMember(Member), MemberLocation(MemberLoc), Args(0), NumArgs(0),
|
||||
CtorOrAnonUnion(C), LParenLoc(L), RParenLoc(R)
|
||||
{
|
||||
if (NumArgs > 0) {
|
||||
this->NumArgs = NumArgs;
|
||||
this->Args = new (Context) Stmt*[NumArgs];
|
||||
for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
|
||||
this->Args[Idx] = Args[Idx];
|
||||
}
|
||||
}
|
||||
|
||||
void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) {
|
||||
for (unsigned I = 0; I != NumArgs; ++I)
|
||||
Args[I]->Destroy(Context);
|
||||
Context.Deallocate(Args);
|
||||
this->~CXXBaseOrMemberInitializer();
|
||||
}
|
||||
|
||||
TypeLoc CXXBaseOrMemberInitializer::getBaseClassLoc() const {
|
||||
if (isBaseInitializer())
|
||||
return BaseOrMember.get<TypeSourceInfo*>()->getTypeLoc();
|
||||
else
|
||||
return TypeLoc();
|
||||
}
|
||||
|
||||
Type *CXXBaseOrMemberInitializer::getBaseClass() {
|
||||
if (isBaseInitializer())
|
||||
return BaseOrMember.get<TypeSourceInfo*>()->getType().getTypePtr();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Type *CXXBaseOrMemberInitializer::getBaseClass() const {
|
||||
if (isBaseInitializer())
|
||||
return BaseOrMember.get<TypeSourceInfo*>()->getType().getTypePtr();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
SourceLocation CXXBaseOrMemberInitializer::getSourceLocation() const {
|
||||
if (isMemberInitializer())
|
||||
return getMemberLocation();
|
||||
|
||||
return getBaseClassLoc().getSourceRange().getBegin();
|
||||
}
|
||||
|
||||
SourceRange CXXBaseOrMemberInitializer::getSourceRange() const {
|
||||
return SourceRange(getSourceLocation(), getRParenLoc());
|
||||
}
|
||||
|
||||
CXXConstructorDecl *
|
||||
CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isExplicit,
|
||||
bool isInline, bool isImplicitlyDeclared) {
|
||||
assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
|
||||
"Name must refer to a constructor");
|
||||
return new (C) CXXConstructorDecl(RD, L, N, T, DInfo, isExplicit, isInline,
|
||||
return new (C) CXXConstructorDecl(RD, L, N, T, TInfo, isExplicit, isInline,
|
||||
isImplicitlyDeclared);
|
||||
}
|
||||
|
||||
@ -790,69 +856,11 @@ CXXConstructorDecl::Destroy(ASTContext& C) {
|
||||
CXXConversionDecl *
|
||||
CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isExplicit) {
|
||||
assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
|
||||
"Name must refer to a conversion function");
|
||||
return new (C) CXXConversionDecl(RD, L, N, T, DInfo, isInline, isExplicit);
|
||||
}
|
||||
|
||||
OverloadedFunctionDecl *
|
||||
OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
DeclarationName N) {
|
||||
return new (C) OverloadedFunctionDecl(DC, N);
|
||||
}
|
||||
|
||||
OverloadIterator::OverloadIterator(NamedDecl *ND) : D(0) {
|
||||
if (!ND)
|
||||
return;
|
||||
|
||||
if (isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND))
|
||||
D = ND;
|
||||
else if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(ND)) {
|
||||
if (Ovl->size() != 0) {
|
||||
D = ND;
|
||||
Iter = Ovl->function_begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) {
|
||||
Functions.push_back(F);
|
||||
this->setLocation(F.get()->getLocation());
|
||||
}
|
||||
|
||||
OverloadIterator::reference OverloadIterator::operator*() const {
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
return FD;
|
||||
|
||||
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
|
||||
return FTD;
|
||||
|
||||
assert(isa<OverloadedFunctionDecl>(D));
|
||||
return *Iter;
|
||||
}
|
||||
|
||||
OverloadIterator &OverloadIterator::operator++() {
|
||||
if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
|
||||
D = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (++Iter == cast<OverloadedFunctionDecl>(D)->function_end())
|
||||
D = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool OverloadIterator::Equals(const OverloadIterator &Other) const {
|
||||
if (!D || !Other.D)
|
||||
return D == Other.D;
|
||||
|
||||
if (D != Other.D)
|
||||
return false;
|
||||
|
||||
return !isa<OverloadedFunctionDecl>(D) || Iter == Other.Iter;
|
||||
return new (C) CXXConversionDecl(RD, L, N, T, TInfo, isInline, isExplicit);
|
||||
}
|
||||
|
||||
FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
|
@ -501,9 +501,9 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
|
||||
|
||||
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
AccessControl ac, Expr *BW) {
|
||||
return new (C) ObjCIvarDecl(DC, L, Id, T, DInfo, ac, BW);
|
||||
return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW);
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,7 +52,6 @@ namespace {
|
||||
void VisitVarDecl(VarDecl *D);
|
||||
void VisitParmVarDecl(ParmVarDecl *D);
|
||||
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
|
||||
void VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D);
|
||||
void VisitNamespaceDecl(NamespaceDecl *D);
|
||||
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
|
||||
void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
|
||||
@ -149,6 +148,17 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
|
||||
}
|
||||
}
|
||||
|
||||
void DeclContext::dumpDeclContext() const {
|
||||
// Get the translation unit
|
||||
const DeclContext *DC = this;
|
||||
while (!DC->isTranslationUnit())
|
||||
DC = DC->getParent();
|
||||
|
||||
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
|
||||
DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0);
|
||||
Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
|
||||
}
|
||||
|
||||
void Decl::dump() const {
|
||||
print(llvm::errs());
|
||||
}
|
||||
@ -362,6 +372,24 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
}
|
||||
|
||||
Proto += ")";
|
||||
|
||||
if (FT && FT->hasExceptionSpec()) {
|
||||
Proto += " throw(";
|
||||
if (FT->hasAnyExceptionSpec())
|
||||
Proto += "...";
|
||||
else
|
||||
for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
|
||||
if (I)
|
||||
Proto += ", ";
|
||||
|
||||
|
||||
std::string ExceptionType;
|
||||
FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy);
|
||||
Proto += ExceptionType;
|
||||
}
|
||||
Proto += ")";
|
||||
}
|
||||
|
||||
if (D->hasAttr<NoReturnAttr>())
|
||||
Proto += " __attribute((noreturn))";
|
||||
if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
@ -488,11 +516,6 @@ void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
|
||||
//----------------------------------------------------------------------------
|
||||
// C++ declarations
|
||||
//----------------------------------------------------------------------------
|
||||
void DeclPrinter::VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D) {
|
||||
assert(false &&
|
||||
"OverloadedFunctionDecls aren't really decls and are never printed");
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
|
||||
Out << "namespace " << D->getNameAsString() << " {\n";
|
||||
VisitDeclContext(D);
|
||||
|
@ -262,8 +262,8 @@ NonTypeTemplateParmDecl *
|
||||
NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, unsigned D, unsigned P,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
DeclaratorInfo *DInfo) {
|
||||
return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, DInfo);
|
||||
TypeSourceInfo *TInfo) {
|
||||
return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo);
|
||||
}
|
||||
|
||||
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
|
||||
|
@ -338,7 +338,7 @@ void DeclarationName::setFETokenInfo(void *T) {
|
||||
|
||||
DeclarationName DeclarationName::getUsingDirectiveName() {
|
||||
// Single instance of DeclarationNameExtra for using-directive
|
||||
static DeclarationNameExtra UDirExtra =
|
||||
static const DeclarationNameExtra UDirExtra =
|
||||
{ DeclarationNameExtra::CXXUsingDirective };
|
||||
|
||||
uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
|
||||
|
@ -110,7 +110,7 @@ void DeclRefExpr::computeDependence() {
|
||||
|
||||
DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D, SourceLocation NameLoc,
|
||||
ValueDecl *D, SourceLocation NameLoc,
|
||||
const TemplateArgumentListInfo *TemplateArgs,
|
||||
QualType T)
|
||||
: Expr(DeclRefExprClass, T, false, false),
|
||||
@ -118,7 +118,6 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
|
||||
(Qualifier? HasQualifierFlag : 0) |
|
||||
(TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)),
|
||||
Loc(NameLoc) {
|
||||
assert(!isa<OverloadedFunctionDecl>(D));
|
||||
if (Qualifier) {
|
||||
NameQualifier *NQ = getNameQualifier();
|
||||
NQ->NNS = Qualifier;
|
||||
@ -134,7 +133,7 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
|
||||
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D,
|
||||
ValueDecl *D,
|
||||
SourceLocation NameLoc,
|
||||
QualType T,
|
||||
const TemplateArgumentListInfo *TemplateArgs) {
|
||||
@ -204,7 +203,8 @@ std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT,
|
||||
}
|
||||
Proto += ")";
|
||||
|
||||
AFT->getResultType().getAsStringInternal(Proto, Policy);
|
||||
if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
|
||||
AFT->getResultType().getAsStringInternal(Proto, Policy);
|
||||
|
||||
Out << Proto;
|
||||
|
||||
@ -471,7 +471,7 @@ QualType CallExpr::getCallReturnType() const {
|
||||
}
|
||||
|
||||
MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||
SourceRange qualrange, NamedDecl *memberdecl,
|
||||
SourceRange qualrange, ValueDecl *memberdecl,
|
||||
SourceLocation l, const TemplateArgumentListInfo *targs,
|
||||
QualType ty)
|
||||
: Expr(MemberExprClass, ty,
|
||||
@ -494,7 +494,7 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
|
||||
NestedNameSpecifier *qual,
|
||||
SourceRange qualrange,
|
||||
NamedDecl *memberdecl,
|
||||
ValueDecl *memberdecl,
|
||||
SourceLocation l,
|
||||
const TemplateArgumentListInfo *targs,
|
||||
QualType ty) {
|
||||
@ -558,12 +558,40 @@ const char *CastExpr::getCastKindName() const {
|
||||
return "FloatingCast";
|
||||
case CastExpr::CK_MemberPointerToBoolean:
|
||||
return "MemberPointerToBoolean";
|
||||
case CastExpr::CK_AnyPointerToObjCPointerCast:
|
||||
return "AnyPointerToObjCPointerCast";
|
||||
case CastExpr::CK_AnyPointerToBlockPointerCast:
|
||||
return "AnyPointerToBlockPointerCast";
|
||||
}
|
||||
|
||||
assert(0 && "Unhandled cast kind!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Expr *CastExpr::getSubExprAsWritten() {
|
||||
Expr *SubExpr = 0;
|
||||
CastExpr *E = this;
|
||||
do {
|
||||
SubExpr = E->getSubExpr();
|
||||
|
||||
// Skip any temporary bindings; they're implicit.
|
||||
if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
|
||||
SubExpr = Binder->getSubExpr();
|
||||
|
||||
// Conversions by constructor and conversion functions have a
|
||||
// subexpression describing the call; strip it off.
|
||||
if (E->getCastKind() == CastExpr::CK_ConstructorConversion)
|
||||
SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
|
||||
else if (E->getCastKind() == CastExpr::CK_UserDefinedConversion)
|
||||
SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
|
||||
|
||||
// If the subexpression we're left with is an implicit cast, look
|
||||
// through that, too.
|
||||
} while ((E = dyn_cast<ImplicitCastExpr>(SubExpr)));
|
||||
|
||||
return SubExpr;
|
||||
}
|
||||
|
||||
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
|
||||
/// corresponds to, e.g. "<<=".
|
||||
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
|
||||
@ -944,8 +972,7 @@ static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {
|
||||
return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||
|
||||
// C++ 3.10p2: An lvalue refers to an object or function.
|
||||
(Ctx.getLangOptions().CPlusPlus &&
|
||||
(isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl) ||
|
||||
isa<FunctionTemplateDecl>(Decl)));
|
||||
(isa<FunctionDecl>(Decl) || isa<FunctionTemplateDecl>(Decl)));
|
||||
}
|
||||
|
||||
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an
|
||||
@ -982,6 +1009,7 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
|
||||
// Check whether the expression can be sanely treated like an l-value
|
||||
Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
|
||||
switch (getStmtClass()) {
|
||||
case ObjCIsaExprClass:
|
||||
case StringLiteralClass: // C99 6.5.1p4
|
||||
case ObjCEncodeExprClass: // @encode behaves like its string in every way.
|
||||
return LV_Valid;
|
||||
@ -1343,6 +1371,13 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Expr::isDefaultArgument() const {
|
||||
const Expr *E = this;
|
||||
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
|
||||
E = ICE->getSubExprAsWritten();
|
||||
|
||||
return isa<CXXDefaultArgExpr>(E);
|
||||
}
|
||||
|
||||
/// hasAnyTypeDependentArguments - Determines if any of the expressions
|
||||
/// in Exprs is type-dependent.
|
||||
@ -1598,13 +1633,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
||||
// constant expression (5.19). In that case, the member can appear
|
||||
// in integral constant expressions.
|
||||
if (Def->isOutOfLine()) {
|
||||
Dcl->setInitKnownICE(Ctx, false);
|
||||
Dcl->setInitKnownICE(false);
|
||||
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
||||
}
|
||||
|
||||
|
||||
if (Dcl->isCheckingICE()) {
|
||||
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
||||
}
|
||||
|
||||
Dcl->setCheckingICE();
|
||||
ICEDiag Result = CheckICE(Init, Ctx);
|
||||
// Cache the result of the ICE test.
|
||||
Dcl->setInitKnownICE(Ctx, Result.Val == 0);
|
||||
Dcl->setInitKnownICE(Result.Val == 0);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
@ -1804,7 +1844,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
|
||||
}
|
||||
EvalResult EvalResult;
|
||||
if (!Evaluate(EvalResult, Ctx))
|
||||
llvm::llvm_unreachable("ICE cannot be evaluated!");
|
||||
llvm_unreachable("ICE cannot be evaluated!");
|
||||
assert(!EvalResult.HasSideEffects && "ICE with side effects!");
|
||||
assert(EvalResult.Val.isInt() && "ICE that isn't integer!");
|
||||
Result = EvalResult.Val.getInt();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user