aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-01-23 11:10:26 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-01-23 11:10:26 +0000
commit5044f5c816adfd5cba17f1adee1a10127296d0bf (patch)
treec69d3f4f13d508570bb5257a6aea735f88bdf09c
parentee791dde723a2089c681d2ab6a9d4f96379d5f49 (diff)
downloadsrc-5044f5c816adfd5cba17f1adee1a10127296d0bf.tar.gz
src-5044f5c816adfd5cba17f1adee1a10127296d0bf.zip
Update clang to r94309.
Notes
Notes: svn path=/vendor/clang/dist/; revision=202879
-rw-r--r--clang.xcodeproj/project.pbxproj48
-rw-r--r--include/clang-c/Index.h896
-rw-r--r--include/clang/AST/ASTContext.h16
-rw-r--r--include/clang/AST/CXXInheritance.h16
-rw-r--r--include/clang/AST/Decl.h26
-rw-r--r--include/clang/AST/DeclBase.h12
-rw-r--r--include/clang/AST/DeclCXX.h22
-rw-r--r--include/clang/AST/DeclObjC.h150
-rw-r--r--include/clang/AST/Expr.h39
-rw-r--r--include/clang/AST/ExprCXX.h48
-rw-r--r--include/clang/AST/Type.h108
-rw-r--r--include/clang/AST/TypeLoc.h112
-rw-r--r--include/clang/AST/TypeLocVisitor.h1
-rw-r--r--include/clang/AST/UnresolvedSet.h211
-rw-r--r--include/clang/Analysis/CFG.h40
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisContext.h11
-rw-r--r--include/clang/Analysis/PathSensitive/CheckerVisitor.h5
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h4
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h3
-rw-r--r--include/clang/Basic/Builtins.def1
-rw-r--r--include/clang/Basic/BuiltinsX86.def6
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td33
-rw-r--r--include/clang/Basic/MacroBuilder.h46
-rw-r--r--include/clang/Basic/Makefile6
-rw-r--r--include/clang/Basic/Specifiers.h82
-rw-r--r--include/clang/Basic/Version.h24
-rw-r--r--include/clang/Driver/Driver.h3
-rw-r--r--include/clang/Frontend/ASTUnit.h17
-rw-r--r--include/clang/Frontend/PCHBitCodes.h20
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h22
-rw-r--r--include/clang/Frontend/Utils.h23
-rw-r--r--include/clang/Lex/Preprocessor.h18
-rw-r--r--include/clang/Parse/AccessSpecifier.h30
-rw-r--r--include/clang/Parse/Action.h6
-rw-r--r--include/clang/Parse/DeclSpec.h85
-rw-r--r--include/clang/Parse/Parser.h2
-rw-r--r--include/clang/Rewrite/DeltaTree.h2
-rw-r--r--lib/AST/ASTContext.cpp104
-rw-r--r--lib/AST/CXXInheritance.cpp36
-rw-r--r--lib/AST/Decl.cpp8
-rw-r--r--lib/AST/DeclBase.cpp20
-rw-r--r--lib/AST/DeclCXX.cpp12
-rw-r--r--lib/AST/DeclObjC.cpp48
-rw-r--r--lib/AST/Expr.cpp10
-rw-r--r--lib/AST/ExprCXX.cpp9
-rw-r--r--lib/AST/ExprConstant.cpp9
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp5
-rw-r--r--lib/AST/Type.cpp39
-rw-r--r--lib/AST/TypeLoc.cpp54
-rw-r--r--lib/Analysis/AnalysisContext.cpp2
-rw-r--r--lib/Analysis/ArrayBoundChecker.cpp3
-rw-r--r--lib/Analysis/CFG.cpp292
-rw-r--r--lib/Analysis/CastToStructChecker.cpp2
-rw-r--r--lib/Analysis/GRExprEngine.cpp76
-rw-r--r--lib/Analysis/MallocChecker.cpp22
-rw-r--r--lib/Analysis/RegionStore.cpp25
-rw-r--r--lib/Analysis/ReturnPointerRangeChecker.cpp3
-rw-r--r--lib/Basic/Makefile5
-rw-r--r--lib/Basic/Targets.cpp2
-rw-r--r--lib/Basic/Version.cpp42
-rw-r--r--lib/CodeGen/CGBlocks.cpp26
-rw-r--r--lib/CodeGen/CGBuiltin.cpp13
-rw-r--r--lib/CodeGen/CGClass.cpp24
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp193
-rw-r--r--lib/CodeGen/CGDebugInfo.h8
-rw-r--r--lib/CodeGen/CGExprConstant.cpp14
-rw-r--r--lib/CodeGen/CGObjC.cpp3
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp25
-rw-r--r--lib/CodeGen/CGObjCMac.cpp6
-rw-r--r--lib/CodeGen/CGObjCRuntime.h2
-rw-r--r--lib/CodeGen/CGVTT.cpp398
-rw-r--r--lib/CodeGen/CGVtable.cpp444
-rw-r--r--lib/CodeGen/CMakeLists.txt1
-rw-r--r--lib/CodeGen/CodeGenModule.cpp9
-rw-r--r--lib/CodeGen/CodeGenModule.h5
-rw-r--r--lib/CodeGen/TargetABIInfo.cpp1821
-rw-r--r--lib/CodeGen/TargetInfo.cpp14
-rw-r--r--lib/CodeGen/TargetInfo.h4
-rw-r--r--lib/Driver/Driver.cpp28
-rw-r--r--lib/Driver/Makefile3
-rw-r--r--lib/Driver/ToolChains.cpp145
-rw-r--r--lib/Driver/ToolChains.h5
-rw-r--r--lib/Driver/Tools.cpp104
-rw-r--r--lib/Driver/Tools.h1
-rw-r--r--lib/Frontend/ASTConsumers.cpp5
-rw-r--r--lib/Frontend/ASTUnit.cpp32
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp98
-rw-r--r--lib/Frontend/CacheTokens.cpp38
-rw-r--r--lib/Frontend/DeclXML.cpp4
-rw-r--r--lib/Frontend/HTMLDiagnostics.cpp24
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp26
-rw-r--r--lib/Frontend/InitPreprocessor.cpp47
-rw-r--r--lib/Frontend/PCHReader.cpp33
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp38
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp60
-rw-r--r--lib/Frontend/PCHWriter.cpp31
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp24
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp41
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp56
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp4
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp24
-rw-r--r--lib/Frontend/RewriteObjC.cpp262
-rw-r--r--lib/Frontend/StmtXML.cpp34
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp36
-rw-r--r--lib/Frontend/TypeXML.cpp4
-rw-r--r--lib/Index/ResolveLocation.cpp2
-rw-r--r--lib/Lex/Lexer.cpp42
-rw-r--r--lib/Lex/LiteralSupport.cpp2
-rw-r--r--lib/Lex/PPDirectives.cpp20
-rw-r--r--lib/Lex/PPMacroExpansion.cpp4
-rw-r--r--lib/Lex/Pragma.cpp3
-rw-r--r--lib/Lex/Preprocessor.cpp31
-rwxr-xr-xlib/Makefile4
-rw-r--r--lib/Parse/DeclSpec.cpp19
-rw-r--r--lib/Parse/MinimalAction.cpp1
-rw-r--r--lib/Parse/ParseDeclCXX.cpp38
-rw-r--r--lib/Parse/ParseObjc.cpp3
-rw-r--r--lib/Parse/Parser.cpp3
-rw-r--r--lib/Rewrite/DeltaTree.cpp2
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp4
-rw-r--r--lib/Sema/Lookup.h104
-rw-r--r--lib/Sema/Sema.h69
-rw-r--r--lib/Sema/SemaAccess.cpp99
-rw-r--r--lib/Sema/SemaCXXCast.cpp31
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp26
-rw-r--r--lib/Sema/SemaChecking.cpp527
-rw-r--r--lib/Sema/SemaCodeComplete.cpp36
-rw-r--r--lib/Sema/SemaDecl.cpp418
-rw-r--r--lib/Sema/SemaDeclCXX.cpp59
-rw-r--r--lib/Sema/SemaDeclObjC.cpp214
-rw-r--r--lib/Sema/SemaExpr.cpp112
-rw-r--r--lib/Sema/SemaExprCXX.cpp20
-rw-r--r--lib/Sema/SemaExprObjC.cpp12
-rw-r--r--lib/Sema/SemaInit.cpp38
-rw-r--r--lib/Sema/SemaInit.h15
-rw-r--r--lib/Sema/SemaLookup.cpp42
-rw-r--r--lib/Sema/SemaOverload.cpp269
-rw-r--r--lib/Sema/SemaOverload.h11
-rw-r--r--lib/Sema/SemaStmt.cpp8
-rw-r--r--lib/Sema/SemaTemplate.cpp25
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp57
-rw-r--r--lib/Sema/SemaType.cpp15
-rw-r--r--lib/Sema/TreeTransform.h133
-rw-r--r--test/Analysis/NSString-failed-cases.m115
-rw-r--r--test/Analysis/malloc.c6
-rw-r--r--test/Analysis/misc-ps.m26
-rw-r--r--test/Analysis/outofbound.c10
-rw-r--r--test/CXX/class.access/class.access.base/p1.cpp152
-rw-r--r--test/CodeCompletion/call.c15
-rw-r--r--test/CodeGen/2009-10-20-GlobalDebug.c2
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-3.cpp20
-rw-r--r--test/CodeGenCXX/debug-info.cpp6
-rw-r--r--test/CodeGenCXX/member-function-pointers.cpp11
-rw-r--r--test/CodeGenCXX/temp-order.cpp9
-rw-r--r--test/CodeGenCXX/virt.cpp790
-rw-r--r--test/CodeGenCXX/vtt-layout.cpp64
-rw-r--r--test/Driver/darwin-arm.c4
-rw-r--r--test/FixIt/typo.m1
-rw-r--r--test/Index/Inputs/remap-load-to.c3
-rw-r--r--test/Index/TestClassDecl.m29
-rw-r--r--test/Index/TestClassForwardDecl.m25
-rw-r--r--test/Index/c-index-api-fn-scan.m217
-rw-r--r--test/Index/c-index-api-loadTU-test.m106
-rw-r--r--test/Index/c-index-getCursor-test.m175
-rw-r--r--test/Index/cindex-from-source.m6
-rw-r--r--test/Index/comments.c34
-rw-r--r--test/Index/find-decls.c25
-rw-r--r--test/Index/find-defs.c18
-rw-r--r--test/Index/find-refs.c47
-rw-r--r--test/Index/load-exprs.c13
-rw-r--r--test/Index/multiple-redecls.c12
-rw-r--r--test/Index/objc-decls.m16
-rw-r--r--test/Index/objc-message.m38
-rw-r--r--test/Index/remap-cursor-at.c5
-rw-r--r--test/Index/remap-load.c13
-rw-r--r--test/Index/resolve-loc.c37
-rw-r--r--test/Lexer/constants-ms.c15
-rw-r--r--test/Misc/tabstop.c20
-rw-r--r--test/PCH/cxx_exprs.cpp26
-rw-r--r--test/PCH/cxx_exprs.h21
-rw-r--r--test/Preprocessor/foo.framework/Headers/bar.h3
-rw-r--r--test/Preprocessor/foo.framework/Headers/foo.h6
-rw-r--r--test/Preprocessor/framework-include.m5
-rw-r--r--test/Rewriter/rewrite-byref-vars.mm11
-rw-r--r--test/Rewriter/rewrite-extern-c.mm8
-rw-r--r--test/Rewriter/rewrite-protocol-type-1.m3
-rw-r--r--test/Rewriter/rewrite-typeof.mm20
-rw-r--r--test/Sema/block-literal.c3
-rw-r--r--test/Sema/block-misc.c3
-rw-r--r--test/Sema/compound-literal.c3
-rw-r--r--test/Sema/scope-check.c11
-rw-r--r--test/Sema/warn-unreachable.c82
-rw-r--r--test/SemaCXX/access-control-check.cpp7
-rw-r--r--test/SemaCXX/anonymous-union.cpp10
-rw-r--r--test/SemaCXX/enum.cpp11
-rw-r--r--test/SemaCXX/new-delete.cpp2
-rw-r--r--test/SemaCXX/overload-call.cpp14
-rw-r--r--test/SemaCXX/unused.cpp9
-rw-r--r--test/SemaCXX/virtual-override.cpp58
-rw-r--r--test/SemaCXX/warn-unreachable.cpp76
-rw-r--r--test/SemaObjC/method-unused-attribute.m15
-rw-r--r--test/SemaObjC/property-category-2.m5
-rw-r--r--test/SemaObjC/property-category-impl.m31
-rw-r--r--test/SemaObjC/property-user-setter.m15
-rw-r--r--test/SemaObjC/property.m5
-rw-r--r--test/SemaObjC/super.m7
-rw-r--r--test/SemaObjC/unimplemented-protocol-prop.m20
-rw-r--r--test/SemaObjCXX/cstyle-block-pointer-cast.mm42
-rw-r--r--test/SemaObjCXX/pointer-to-objc-pointer-conv.mm21
-rw-r--r--test/SemaTemplate/dependent-base-classes.cpp28
-rw-r--r--test/SemaTemplate/dependent-base-member-init.cpp23
-rw-r--r--test/SemaTemplate/dependent-expr.cpp19
-rw-r--r--test/SemaTemplate/friend-template.cpp18
-rw-r--r--test/SemaTemplate/instantiate-local-class.cpp34
-rw-r--r--test/SemaTemplate/member-template-access-expr.cpp20
-rw-r--r--tools/CIndex/CIndex.cpp1920
-rw-r--r--tools/CIndex/CIndex.exports39
-rw-r--r--tools/CIndex/CIndexCodeCompletion.cpp31
-rw-r--r--tools/CIndex/CIndexUSRs.cpp134
-rw-r--r--tools/CIndex/CIndexer.cpp37
-rw-r--r--tools/CIndex/CIndexer.h30
-rw-r--r--tools/CIndex/CMakeLists.txt4
-rw-r--r--tools/CIndex/CXCursor.cpp305
-rw-r--r--tools/CIndex/CXCursor.h88
-rw-r--r--tools/CIndex/Makefile2
-rw-r--r--tools/CMakeLists.txt1
-rw-r--r--tools/Makefile2
-rw-r--r--tools/c-index-test/c-index-test.c469
-rw-r--r--tools/driver/CMakeLists.txt2
-rw-r--r--tools/driver/Makefile2
-rw-r--r--utils/OptionalTests/Extra/README.txt3
-rw-r--r--utils/OptionalTests/Extra/Runtime/darwin-clang_rt.c338
-rw-r--r--utils/OptionalTests/README.txt4
-rw-r--r--utils/OptionalTests/lit.cfg26
-rw-r--r--www/analyzer/scan-build.html2
-rw-r--r--www/hacking.html22
238 files changed, 9431 insertions, 6572 deletions
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index ea72c9e6f04f..d1cd032ec033 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -21,7 +21,6 @@
1A2A54BD0FD1DD1C00F4CE45 /* HTMLPrint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */; };
1A2A54BE0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AD0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp */; };
1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */; };
- 1A2A54C00FD1DD1C00F4CE45 /* RewriteBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AF0FD1DD1C00F4CE45 /* RewriteBlocks.cpp */; };
1A2A54C10FD1DD1C00F4CE45 /* RewriteMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B00FD1DD1C00F4CE45 /* RewriteMacros.cpp */; };
1A2A54C20FD1DD1C00F4CE45 /* RewriteObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B10FD1DD1C00F4CE45 /* RewriteObjC.cpp */; };
1A2A54C30FD1DD1C00F4CE45 /* RewriteTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B20FD1DD1C00F4CE45 /* RewriteTest.cpp */; };
@@ -44,10 +43,20 @@
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 */; };
+ 1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A97825A1108BA18002B98FC /* CGVTT.cpp */; };
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; };
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA963C310D85A7300786C86 /* FullExpr.cpp */; };
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
+ 1ACB57E41105820D0047B991 /* CompilerInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */; };
+ 1ACB57E51105820D0047B991 /* CompilerInvocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */; };
+ 1ACB57E61105820D0047B991 /* DeclXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DD1105820D0047B991 /* DeclXML.cpp */; };
+ 1ACB57E71105820D0047B991 /* FrontendAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DE1105820D0047B991 /* FrontendAction.cpp */; };
+ 1ACB57E81105820D0047B991 /* FrontendActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DF1105820D0047B991 /* FrontendActions.cpp */; };
+ 1ACB57E91105820D0047B991 /* FrontendOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E01105820D0047B991 /* FrontendOptions.cpp */; };
+ 1ACB57EA1105820D0047B991 /* LangStandards.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E11105820D0047B991 /* LangStandards.cpp */; };
+ 1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E21105820D0047B991 /* TypeXML.cpp */; };
+ 1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E31105820D0047B991 /* VerifyDiagnosticsClient.cpp */; };
1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795110A90C6100741BBA /* TypePrinter.cpp */; };
1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795210A90C6100741BBA /* TypeLoc.cpp */; };
1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795310A90C6100741BBA /* TemplateBase.cpp */; };
@@ -59,7 +68,6 @@
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */; };
- 352246E90F5C6BE000D0D279 /* ManagerRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E30F5C6BE000D0D279 /* ManagerRegistry.cpp */; };
352246EA0F5C6BE000D0D279 /* PlistDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E40F5C6BE000D0D279 /* PlistDiagnostics.cpp */; };
352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */; };
352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */; };
@@ -360,7 +368,6 @@
1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLPrint.cpp; path = lib/Frontend/HTMLPrint.cpp; sourceTree = "<group>"; };
1A2A54AD0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PrintParserCallbacks.cpp; path = lib/Frontend/PrintParserCallbacks.cpp; sourceTree = "<group>"; };
1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PrintPreprocessedOutput.cpp; path = lib/Frontend/PrintPreprocessedOutput.cpp; sourceTree = "<group>"; };
- 1A2A54AF0FD1DD1C00F4CE45 /* RewriteBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteBlocks.cpp; path = lib/Frontend/RewriteBlocks.cpp; sourceTree = "<group>"; };
1A2A54B00FD1DD1C00F4CE45 /* RewriteMacros.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteMacros.cpp; path = lib/Frontend/RewriteMacros.cpp; sourceTree = "<group>"; };
1A2A54B10FD1DD1C00F4CE45 /* RewriteObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteObjC.cpp; path = lib/Frontend/RewriteObjC.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A2A54B20FD1DD1C00F4CE45 /* RewriteTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteTest.cpp; path = lib/Frontend/RewriteTest.cpp; sourceTree = "<group>"; };
@@ -398,6 +405,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>"; };
+ 1A97825A1108BA18002B98FC /* CGVTT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGVTT.cpp; path = lib/CodeGen/CGVTT.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; };
@@ -405,6 +413,15 @@
1AA963C310D85A7300786C86 /* FullExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = FullExpr.cpp; path = lib/AST/FullExpr.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; tabWidth = 2; };
+ 1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerInstance.cpp; path = lib/Frontend/CompilerInstance.cpp; sourceTree = "<group>"; };
+ 1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerInvocation.cpp; path = lib/Frontend/CompilerInvocation.cpp; sourceTree = "<group>"; };
+ 1ACB57DD1105820D0047B991 /* DeclXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeclXML.cpp; path = lib/Frontend/DeclXML.cpp; sourceTree = "<group>"; };
+ 1ACB57DE1105820D0047B991 /* FrontendAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FrontendAction.cpp; path = lib/Frontend/FrontendAction.cpp; sourceTree = "<group>"; };
+ 1ACB57DF1105820D0047B991 /* FrontendActions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FrontendActions.cpp; path = lib/Frontend/FrontendActions.cpp; sourceTree = "<group>"; };
+ 1ACB57E01105820D0047B991 /* FrontendOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FrontendOptions.cpp; path = lib/Frontend/FrontendOptions.cpp; sourceTree = "<group>"; };
+ 1ACB57E11105820D0047B991 /* LangStandards.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LangStandards.cpp; path = lib/Frontend/LangStandards.cpp; sourceTree = "<group>"; };
+ 1ACB57E21105820D0047B991 /* TypeXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeXML.cpp; path = lib/Frontend/TypeXML.cpp; sourceTree = "<group>"; };
+ 1ACB57E31105820D0047B991 /* VerifyDiagnosticsClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VerifyDiagnosticsClient.cpp; path = lib/Frontend/VerifyDiagnosticsClient.cpp; sourceTree = "<group>"; };
1ADD795110A90C6100741BBA /* TypePrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypePrinter.cpp; path = lib/AST/TypePrinter.cpp; sourceTree = "<group>"; };
1ADD795210A90C6100741BBA /* TypeLoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeLoc.cpp; path = lib/AST/TypeLoc.cpp; sourceTree = "<group>"; };
1ADD795310A90C6100741BBA /* TemplateBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateBase.cpp; path = lib/AST/TemplateBase.cpp; sourceTree = "<group>"; };
@@ -418,7 +435,6 @@
3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckObjCInstMethSignature.cpp; path = lib/Analysis/CheckObjCInstMethSignature.cpp; sourceTree = "<group>"; };
352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLDiagnostics.cpp; path = lib/Frontend/HTMLDiagnostics.cpp; sourceTree = "<group>"; };
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitHeaderSearch.cpp; path = lib/Frontend/InitHeaderSearch.cpp; sourceTree = "<group>"; };
- 352246E30F5C6BE000D0D279 /* ManagerRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ManagerRegistry.cpp; path = lib/Frontend/ManagerRegistry.cpp; sourceTree = "<group>"; };
352246E40F5C6BE000D0D279 /* PlistDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlistDiagnostics.cpp; path = lib/Frontend/PlistDiagnostics.cpp; sourceTree = "<group>"; };
352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TextDiagnosticBuffer.cpp; path = lib/Frontend/TextDiagnosticBuffer.cpp; sourceTree = "<group>"; };
352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TextDiagnosticPrinter.cpp; path = lib/Frontend/TextDiagnosticPrinter.cpp; sourceTree = "<group>"; };
@@ -922,16 +938,22 @@
1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */,
1A2A54A60FD1DD1C00F4CE45 /* Backend.cpp */,
1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */,
+ 1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */,
+ 1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */,
+ 1ACB57DD1105820D0047B991 /* DeclXML.cpp */,
1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */,
1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */,
1A2A54AA0FD1DD1C00F4CE45 /* DocumentXML.cpp */,
DEF1683F0F9548DC0098507F /* FixItRewriter.cpp */,
+ 1ACB57DE1105820D0047B991 /* FrontendAction.cpp */,
+ 1ACB57DF1105820D0047B991 /* FrontendActions.cpp */,
+ 1ACB57E01105820D0047B991 /* FrontendOptions.cpp */,
1A2A54AB0FD1DD1C00F4CE45 /* GeneratePCH.cpp */,
352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */,
1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */,
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */,
DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */,
- 352246E30F5C6BE000D0D279 /* ManagerRegistry.cpp */,
+ 1ACB57E11105820D0047B991 /* LangStandards.cpp */,
DEF165740F8FB3510098507F /* PCHReader.cpp */,
DECB77780FA579B000F5FBC7 /* PCHReaderDecl.cpp */,
DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */,
@@ -943,11 +965,12 @@
1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */,
352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */,
352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */,
- 1A2A54AF0FD1DD1C00F4CE45 /* RewriteBlocks.cpp */,
+ 1ACB57E21105820D0047B991 /* TypeXML.cpp */,
1A2A54B00FD1DD1C00F4CE45 /* RewriteMacros.cpp */,
1A2A54B10FD1DD1C00F4CE45 /* RewriteObjC.cpp */,
1A2A54B20FD1DD1C00F4CE45 /* RewriteTest.cpp */,
1A2A54B30FD1DD1C00F4CE45 /* StmtXML.cpp */,
+ 1ACB57E31105820D0047B991 /* VerifyDiagnosticsClient.cpp */,
1A2A54B40FD1DD1C00F4CE45 /* Warnings.cpp */,
);
name = Frontend;
@@ -1296,6 +1319,7 @@
35475B230E7997680000BFE4 /* CGValue.h */,
1A81AA18108144F40094E50B /* CGVtable.cpp */,
1A81AA5D108278A20094E50B /* CGVtable.h */,
+ 1A97825A1108BA18002B98FC /* CGVTT.cpp */,
DE928B800C0A615B00231DA4 /* CodeGenFunction.h */,
DE928B820C0A616000231DA4 /* CodeGenFunction.cpp */,
DE928B7C0C0A615100231DA4 /* CodeGenModule.h */,
@@ -1844,7 +1868,6 @@
DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */,
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */,
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */,
- 352246E90F5C6BE000D0D279 /* ManagerRegistry.cpp in Sources */,
352246EA0F5C6BE000D0D279 /* PlistDiagnostics.cpp in Sources */,
352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */,
352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */,
@@ -1892,7 +1915,6 @@
1A2A54BD0FD1DD1C00F4CE45 /* HTMLPrint.cpp in Sources */,
1A2A54BE0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp in Sources */,
1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */,
- 1A2A54C00FD1DD1C00F4CE45 /* RewriteBlocks.cpp in Sources */,
1A2A54C10FD1DD1C00F4CE45 /* RewriteMacros.cpp in Sources */,
1A2A54C20FD1DD1C00F4CE45 /* RewriteObjC.cpp in Sources */,
1A2A54C30FD1DD1C00F4CE45 /* RewriteTest.cpp in Sources */,
@@ -1935,6 +1957,16 @@
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */,
E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */,
1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */,
+ 1ACB57E41105820D0047B991 /* CompilerInstance.cpp in Sources */,
+ 1ACB57E51105820D0047B991 /* CompilerInvocation.cpp in Sources */,
+ 1ACB57E61105820D0047B991 /* DeclXML.cpp in Sources */,
+ 1ACB57E71105820D0047B991 /* FrontendAction.cpp in Sources */,
+ 1ACB57E81105820D0047B991 /* FrontendActions.cpp in Sources */,
+ 1ACB57E91105820D0047B991 /* FrontendOptions.cpp in Sources */,
+ 1ACB57EA1105820D0047B991 /* LangStandards.cpp in Sources */,
+ 1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */,
+ 1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */,
+ 1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index f11a9eb76f43..ef17ed1ca8be 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -34,77 +34,42 @@ extern "C" {
#define CINDEX_LINKAGE
#endif
-/*
- Clang indeX abstractions. The backing store for the following API's will be
- clangs AST file (currently based on PCH). AST files are created as follows:
-
- "clang -emit-ast <sourcefile.langsuffix> -o <sourcefile.ast>".
-
- Naming Conventions: To avoid namespace pollution, data types are prefixed
- with "CX" and functions are prefixed with "clang_".
-*/
-typedef void *CXIndex; /* An indexing instance. */
+/** \defgroup CINDEX C Interface to Clang
+ *
+ * The C Interface to Clang provides a relatively small API that exposes
+ * facilities for parsing source code into an abstract syntax tree (AST),
+ * loading already-parsed ASTs, traversing the AST, associating
+ * physical source locations with elements within the AST, and other
+ * facilities that support Clang-based development tools.
+ *
+ * This C interface to Clang will never provide all of the information
+ * representation stored in Clang's C++ AST, nor should it: the intent is to
+ * maintain an API that is relatively stable from one release to the next,
+ * providing only the basic functionality needed to support development tools.
+ *
+ * To avoid namespace pollution, data types are prefixed with "CX" and
+ * functions are prefixed with "clang_".
+ *
+ * @{
+ */
+
+/**
+ * \brief An "index" that consists of a set of translation units that would
+ * typically be linked together into an executable or library.
+ */
+typedef void *CXIndex;
+/**
+ * \brief A single translation unit, which resides in an index.
+ */
typedef void *CXTranslationUnit; /* A translation unit instance. */
-typedef void *CXFile; /* A source file */
-typedef void *CXDecl; /* A specific declaration within a translation unit. */
-typedef void *CXStmt; /* A specific statement within a function/method */
-
-/* Cursors represent declarations, definitions, and references. */
-enum CXCursorKind {
- /* Declarations */
- CXCursor_FirstDecl = 1,
- CXCursor_TypedefDecl = 2,
- CXCursor_StructDecl = 3,
- CXCursor_UnionDecl = 4,
- CXCursor_ClassDecl = 5,
- CXCursor_EnumDecl = 6,
- CXCursor_FieldDecl = 7,
- CXCursor_EnumConstantDecl = 8,
- CXCursor_FunctionDecl = 9,
- CXCursor_VarDecl = 10,
- CXCursor_ParmDecl = 11,
- CXCursor_ObjCInterfaceDecl = 12,
- CXCursor_ObjCCategoryDecl = 13,
- CXCursor_ObjCProtocolDecl = 14,
- CXCursor_ObjCPropertyDecl = 15,
- CXCursor_ObjCIvarDecl = 16,
- CXCursor_ObjCInstanceMethodDecl = 17,
- CXCursor_ObjCClassMethodDecl = 18,
- CXCursor_LastDecl = 18,
-
- /* Definitions */
- CXCursor_FirstDefn = 32,
- CXCursor_FunctionDefn = 32,
- CXCursor_ObjCClassDefn = 33,
- CXCursor_ObjCCategoryDefn = 34,
- CXCursor_ObjCInstanceMethodDefn = 35,
- CXCursor_ObjCClassMethodDefn = 36,
- CXCursor_LastDefn = 36,
-
- /* References */
- CXCursor_FirstRef = 40, /* Decl references */
- CXCursor_ObjCSuperClassRef = 40,
- CXCursor_ObjCProtocolRef = 41,
- CXCursor_ObjCClassRef = 42,
-
- CXCursor_ObjCSelectorRef = 43, /* Expression references */
- CXCursor_ObjCIvarRef = 44,
- CXCursor_VarRef = 45,
- CXCursor_FunctionRef = 46,
- CXCursor_EnumConstantRef = 47,
- CXCursor_MemberRef = 48,
- CXCursor_LastRef = 48,
-
- /* Error conditions */
- CXCursor_FirstInvalid = 70,
- CXCursor_InvalidFile = 70,
- CXCursor_NoDeclFound = 71,
- CXCursor_NotImplemented = 72,
- CXCursor_LastInvalid = 72
-};
-
+/**
+ * \brief Opaque pointer representing client data that will be passed through
+ * to various callbacks and visitors.
+ */
+typedef void *CXClientData;
+
/**
* \brief Provides the contents of a file that has not yet been saved to disk.
*
@@ -133,27 +98,19 @@ struct CXUnsavedFile {
unsigned long Length;
};
-/* A cursor into the CXTranslationUnit. */
-
-typedef struct {
- enum CXCursorKind kind;
- CXDecl decl;
- CXStmt stmt; /* expression reference */
- CXDecl referringDecl;
-} CXCursor;
-
-/* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */
-typedef struct {
- CXIndex index;
- void *data;
-} CXEntity;
-
/**
- * For functions returning a string that might or might not need
- * to be internally allocated and freed.
- * Use clang_getCString to access the C string value.
- * Use clang_disposeString to free the value.
- * Treat it as an opaque type.
+ * \defgroup CINDEX_STRING String manipulation routines
+ *
+ * @{
+ */
+
+/**
+ * \brief A character string.
+ *
+ * The \c CXString type is used to return strings from the interface when
+ * the ownership of that string might different from one call to the next.
+ * Use \c clang_getCString() to retrieve the string data and, once finished
+ * with the string data, call \c clang_disposeString() to free the string.
*/
typedef struct {
const char *Spelling;
@@ -162,12 +119,20 @@ typedef struct {
int MustFreeString;
} CXString;
-/* Get C string pointer from a CXString. */
+/**
+ * \brief Retrieve the character data associated with the given string.
+ */
CINDEX_LINKAGE const char *clang_getCString(CXString string);
-/* Free CXString. */
+/**
+ * \brief Free the given string,
+ */
CINDEX_LINKAGE void clang_disposeString(CXString string);
+/**
+ * @}
+ */
+
/**
* \brief clang_createIndex() provides a shared context for creating
* translation units. It provides two options:
@@ -191,14 +156,16 @@ CINDEX_LINKAGE void clang_disposeString(CXString string);
* TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
*
* // This will load all the symbols from 'IndexTest.pch'
- * clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
+ * clang_visitChildren(clang_getTranslationUnitCursor(TU),
+ * TranslationUnitVisitor, 0);
* clang_disposeTranslationUnit(TU);
*
* // This will load all the symbols from 'IndexTest.c', excluding symbols
* // from 'IndexTest.pch'.
* char *args[] = { "-Xclang", "-include-pch=IndexTest.pch", 0 };
* TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args);
- * clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
+ * clang_visitChildren(clang_getTranslationUnitCursor(TU),
+ * TranslationUnitVisitor, 0);
* clang_disposeTranslationUnit(TU);
*
* This process of creating the 'pch', loading it separately, and using it (via
@@ -211,7 +178,7 @@ 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.
*
@@ -224,7 +191,7 @@ clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
CINDEX_LINKAGE void clang_setUseExternalASTGeneration(CXIndex index,
int value);
-/*
+/**
* \brief Create a translation unit from an AST file (-emit-ast).
*/
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
@@ -255,137 +222,632 @@ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
*
* \param source_filename - The name of the source file to load, or NULL if the
* source file is included in clang_command_line_args.
+ *
+ * \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.
*/
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
- CXIndex CIdx,
- const char *source_filename,
- int num_clang_command_line_args,
- const char **clang_command_line_args
-);
+ CXIndex CIdx,
+ const char *source_filename,
+ int num_clang_command_line_args,
+ const char **clang_command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files);
-/*
- Usage: clang_loadTranslationUnit(). Will load the toplevel declarations
- within a translation unit, issuing a 'callback' for each one.
-
- void printObjCInterfaceNames(CXTranslationUnit X, CXCursor C) {
- if (clang_getCursorKind(C) == Cursor_Declaration) {
- CXDecl D = clang_getCursorDecl(C);
- if (clang_getDeclKind(D) == CXDecl_ObjC_interface)
- printf("@interface %s in file %s on line %d column %d\n",
- clang_getDeclSpelling(D), clang_getCursorSource(C),
- clang_getCursorLine(C), clang_getCursorColumn(C));
- }
- }
- static void usage {
- clang_loadTranslationUnit(CXTranslationUnit, printObjCInterfaceNames);
- }
-*/
-typedef void *CXClientData;
-typedef void (*CXTranslationUnitIterator)(CXTranslationUnit, CXCursor,
- CXClientData);
-CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit,
- CXTranslationUnitIterator,
- CXClientData);
-
-/*
- Usage: clang_loadDeclaration(). Will load the declaration, issuing a
- 'callback' for each declaration/reference within the respective declaration.
-
- For interface declarations, this will index the super class, protocols,
- ivars, methods, etc. For structure declarations, this will index the fields.
- For functions, this will index the parameters (and body, for function
- definitions), local declarations/references.
-
- void getInterfaceDetails(CXDecl X, CXCursor C) {
- switch (clang_getCursorKind(C)) {
- case Cursor_ObjC_ClassRef:
- CXDecl SuperClass = clang_getCursorDecl(C);
- case Cursor_ObjC_ProtocolRef:
- CXDecl AdoptsProtocol = clang_getCursorDecl(C);
- case Cursor_Declaration:
- CXDecl AnIvarOrMethod = clang_getCursorDecl(C);
- }
- }
- static void usage() {
- if (clang_getDeclKind(D) == CXDecl_ObjC_interface) {
- clang_loadDeclaration(D, getInterfaceDetails);
- }
- }
-*/
-typedef void (*CXDeclIterator)(CXDecl, CXCursor, CXClientData);
-
-CINDEX_LINKAGE void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData);
-
-/*
- * CXFile Operations.
+/**
+ * \defgroup CINDEX_FILES File manipulation routines
+ *
+ * @{
+ */
+
+/**
+ * \brief A particular source file that is part of a translation unit.
+ */
+typedef void *CXFile;
+
+
+/**
+ * \brief Retrieve the complete file and path name of the given file.
*/
CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile);
+
+/**
+ * \brief Retrieve the last modification time of the given file.
+ */
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
-/*
- * CXEntity Operations.
+/**
+ * \brief Retrieve a file handle within the given translation unit.
+ *
+ * \param tu the translation unit
+ *
+ * \param file_name the name of the file.
+ *
+ * \returns the file handle for the named file in the translation unit \p tu,
+ * or a NULL file handle if the file was not a part of this translation unit.
*/
+CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
+ const char *file_name);
-/* clang_getDeclaration() maps from a CXEntity to the matching CXDecl (if any)
- * in a specified translation unit. */
-CINDEX_LINKAGE CXDecl clang_getDeclaration(CXEntity, CXTranslationUnit);
+/**
+ * @}
+ */
-/*
- * CXDecl Operations.
+/**
+ * \defgroup CINDEX_LOCATIONS Physical source locations
+ *
+ * Clang represents physical source locations in its abstract syntax tree in
+ * great detail, with file, line, and column information for the majority of
+ * the tokens parsed in the source code. These data types and functions are
+ * used to represent source location information, either for a particular
+ * point in the program or for a range of points in the program, and extract
+ * specific location information from those data types.
+ *
+ * @{
*/
-CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
-CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXIndex, CXDecl);
-CINDEX_LINKAGE CXString clang_getDeclSpelling(CXDecl);
-CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
-CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
-CINDEX_LINKAGE CXString clang_getDeclUSR(CXDecl);
-CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
-CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
+
+/**
+ * \brief Identifies a specific source location within a translation
+ * unit.
+ *
+ * Use clang_getInstantiationLocation() to map a source location to a
+ * particular file, line, and column.
+ */
+typedef struct {
+ void *ptr_data;
+ unsigned int_data;
+} CXSourceLocation;
-typedef struct CXSourceLineColumn {
- unsigned line;
- unsigned column;
-} CXSourceLineColumn;
+/**
+ * \brief Identifies a range of source locations in the source code.
+ *
+ * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
+ * starting and end locations from a source range, respectively.
+ */
+typedef struct {
+ void *ptr_data;
+ unsigned begin_int_data;
+ unsigned end_int_data;
+} CXSourceRange;
+
+/**
+ * \brief Retrieve a NULL (invalid) source location.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getNullLocation();
+
+/**
+ * \determine Determine whether two source locations, which must refer into
+ * the same translation unit, refer to exactly the same point in the source
+ * code.
+ *
+ * \returns non-zero if the source locations refer to the same location, zero
+ * if they refer to different locations.
+ */
+CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
+ CXSourceLocation loc2);
+
+/**
+ * \brief Retrieves the source location associated with a given
+ * file/line/column in a particular translation unit.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
+ CXFile file,
+ unsigned line,
+ unsigned column);
+
+/**
+ * \brief Retrieve a source range given the beginning and ending source
+ * locations.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
+ CXSourceLocation end);
+
+/**
+ * \brief Retrieve the file, line, and column represented by the
+ * given source location.
+ *
+ * \param location the location within a source file that will be
+ * decomposed into its parts.
+ *
+ * \param file if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column if non-NULL, will be set to the column to which the
+ * given source location points.
+ */
+CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column);
+
+/**
+ * \brief Retrieve a source location representing the first
+ * character within a source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
+
+/**
+ * \brief Retrieve a source location representing the last
+ * character within a source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
+
+/**
+ * @}
+ */
-typedef struct CXDeclExtent {
- CXSourceLineColumn begin;
- CXSourceLineColumn end;
-} CXSourceExtent;
+/**
+ * \brief Describes the kind of entity that a cursor refers to.
+ */
+enum CXCursorKind {
+ /* Declarations */
+ CXCursor_FirstDecl = 1,
+ /**
+ * \brief A declaration whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed declarations have the same operations as any other kind
+ * of declaration; one can extract their location information,
+ * spelling, find their definitions, etc. However, the specific kind
+ * of the declaration is not reported.
+ */
+ CXCursor_UnexposedDecl = 1,
+ /** \brief A C or C++ struct. */
+ CXCursor_StructDecl = 2,
+ /** \brief A C or C++ union. */
+ CXCursor_UnionDecl = 3,
+ /** \brief A C++ class. */
+ CXCursor_ClassDecl = 4,
+ /** \brief An enumeration. */
+ CXCursor_EnumDecl = 5,
+ /**
+ * \brief A field (in C) or non-static data member (in C++) in a
+ * struct, union, or C++ class.
+ */
+ CXCursor_FieldDecl = 6,
+ /** \brief An enumerator constant. */
+ CXCursor_EnumConstantDecl = 7,
+ /** \brief A function. */
+ CXCursor_FunctionDecl = 8,
+ /** \brief A variable. */
+ CXCursor_VarDecl = 9,
+ /** \brief A function or method parameter. */
+ CXCursor_ParmDecl = 10,
+ /** \brief An Objective-C @interface. */
+ CXCursor_ObjCInterfaceDecl = 11,
+ /** \brief An Objective-C @interface for a category. */
+ CXCursor_ObjCCategoryDecl = 12,
+ /** \brief An Objective-C @protocol declaration. */
+ CXCursor_ObjCProtocolDecl = 13,
+ /** \brief An Objective-C @property declaration. */
+ CXCursor_ObjCPropertyDecl = 14,
+ /** \brief An Objective-C instance variable. */
+ CXCursor_ObjCIvarDecl = 15,
+ /** \brief An Objective-C instance method. */
+ CXCursor_ObjCInstanceMethodDecl = 16,
+ /** \brief An Objective-C class method. */
+ CXCursor_ObjCClassMethodDecl = 17,
+ /** \brief An Objective-C @implementation. */
+ CXCursor_ObjCImplementationDecl = 18,
+ /** \brief An Objective-C @implementation for a category. */
+ CXCursor_ObjCCategoryImplDecl = 19,
+ /** \brief A typedef */
+ CXCursor_TypedefDecl = 20,
+ CXCursor_LastDecl = 20,
+
+ /* References */
+ CXCursor_FirstRef = 40, /* Decl references */
+ CXCursor_ObjCSuperClassRef = 40,
+ CXCursor_ObjCProtocolRef = 41,
+ CXCursor_ObjCClassRef = 42,
+ /**
+ * \brief A reference to a type declaration.
+ *
+ * A type reference occurs anywhere where a type is named but not
+ * declared. For example, given:
+ *
+ * \code
+ * typedef unsigned size_type;
+ * size_type size;
+ * \endcode
+ *
+ * The typedef is a declaration of size_type (CXCursor_TypedefDecl),
+ * while the type of the variable "size" is referenced. The cursor
+ * referenced by the type of size is the typedef for size_type.
+ */
+ CXCursor_TypeRef = 43,
+ CXCursor_LastRef = 43,
+
+ /* Error conditions */
+ CXCursor_FirstInvalid = 70,
+ CXCursor_InvalidFile = 70,
+ CXCursor_NoDeclFound = 71,
+ CXCursor_NotImplemented = 72,
+ CXCursor_LastInvalid = 72,
+
+ /* Expressions */
+ CXCursor_FirstExpr = 100,
+
+ /**
+ * \brief An expression whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed expressions have the same operations as any other kind
+ * of expression; one can extract their location information,
+ * spelling, children, etc. However, the specific kind of the
+ * expression is not reported.
+ */
+ CXCursor_UnexposedExpr = 100,
+
+ /**
+ * \brief An expression that refers to some value declaration, such
+ * as a function, varible, or enumerator.
+ */
+ CXCursor_DeclRefExpr = 101,
+
+ /**
+ * \brief An expression that refers to a member of a struct, union,
+ * class, Objective-C class, etc.
+ */
+ CXCursor_MemberRefExpr = 102,
+
+ /** \brief An expression that calls a function. */
+ CXCursor_CallExpr = 103,
+
+ /** \brief An expression that sends a message to an Objective-C
+ object or class. */
+ CXCursor_ObjCMessageExpr = 104,
+ CXCursor_LastExpr = 104,
+
+ /* Statements */
+ CXCursor_FirstStmt = 200,
+ /**
+ * \brief A statement whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed statements have the same operations as any other kind of
+ * statement; one can extract their location information, spelling,
+ * children, etc. However, the specific kind of the statement is not
+ * reported.
+ */
+ CXCursor_UnexposedStmt = 200,
+ CXCursor_LastStmt = 200,
+
+ /**
+ * \brief Cursor that represents the translation unit itself.
+ *
+ * The translation unit cursor exists primarily to act as the root
+ * cursor for traversing the contents of a translation unit.
+ */
+ CXCursor_TranslationUnit = 300
+};
-/* clang_getDeclExtent() returns the physical extent of a declaration. The
- * beginning line/column pair points to the start of the first token in the
- * declaration, and the ending line/column pair points to the last character in
- * the last token of the declaration.
+/**
+ * \brief A cursor representing some element in the abstract syntax tree for
+ * a translation unit.
+ *
+ * The cursor abstraction unifies the different kinds of entities in a
+ * program--declaration, statements, expressions, references to declarations,
+ * etc.--under a single "cursor" abstraction with a common set of operations.
+ * Common operation for a cursor include: getting the physical location in
+ * a source file where the cursor points, getting the name associated with a
+ * cursor, and retrieving cursors for any child nodes of a particular cursor.
+ *
+ * Cursors can be produced in two specific ways.
+ * clang_getTranslationUnitCursor() produces a cursor for a translation unit,
+ * from which one can use clang_visitChildren() to explore the rest of the
+ * translation unit. clang_getCursor() maps from a physical source location
+ * to the entity that resides at that location, allowing one to map from the
+ * source code into the AST.
*/
-CINDEX_LINKAGE CXSourceExtent clang_getDeclExtent(CXDecl);
+typedef struct {
+ enum CXCursorKind kind;
+ void *data[3];
+} CXCursor;
-/*
- * CXCursor Operations.
+/**
+ * \defgroup CINDEX_CURSOR_MANIP Cursor manipulations
+ *
+ * @{
*/
+
/**
- Usage: clang_getCursor() will translate a source/line/column position
- into an AST cursor (to derive semantic information from the source code).
+ * \brief Retrieve the NULL cursor, which represents no entity.
*/
-CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit,
- const char *source_name,
- unsigned line, unsigned column);
-
CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
+
+/**
+ * \brief Retrieve the cursor that represents the given translation unit.
+ *
+ * The translation unit cursor can be used to start traversing the
+ * various declarations within the given translation unit.
+ */
+CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
+/**
+ * \brief Determine whether two cursors are equivalent.
+ */
+CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
+
+/**
+ * \brief Retrieve the kind of the given cursor.
+ */
CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
+
+/**
+ * \brief Determine whether the given cursor kind represents a declaration.
+ */
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents a simple
+ * reference.
+ *
+ * Note that other kinds of cursors (such as expressions) can also refer to
+ * other cursors. Use clang_getCursorReferenced() to determine whether a
+ * particular cursor refers to another entity.
+ */
CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
-CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents an expression.
+ */
+CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents a statement.
+ */
+CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents an invalid
+ * cursor.
+ */
CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
-CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
+/**
+ * \brief Determine whether the given cursor kind represents a translation
+ * unit.
+ */
+CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CURSOR_SOURCE Mapping between cursors and source code
+ *
+ * Cursors represent a location within the Abstract Syntax Tree (AST). These
+ * routines help map between cursors and the physical locations where the
+ * described entities occur in the source code. The mapping is provided in
+ * both directions, so one can map from source code to the AST and back.
+ *
+ * @{
+ */
+
+/**
+ * \brief Map a source location to the cursor that describes the entity at that
+ * location in the source code.
+ *
+ * clang_getCursor() maps an arbitrary source location within a translation
+ * unit down to the most specific cursor that describes the entity at that
+ * location. For example, given an expression \c x + y, invoking
+ * clang_getCursor() with a source location pointing to "x" will return the
+ * cursor for "x"; similarly for "y". If the cursor points anywhere between
+ * "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor()
+ * will return a cursor referring to the "+" expression.
+ *
+ * \returns a cursor representing the entity at the given source location, or
+ * a NULL cursor if no such entity can be found.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation);
+
+/**
+ * \brief Retrieve the physical location of the source constructor referenced
+ * by the given cursor.
+ *
+ * The location of a declaration is typically the location of the name of that
+ * declaration, where the name of that declaration would occur if it is
+ * unnamed, or some keyword that introduces that particular declaration.
+ * The location of a reference is where that reference occurs within the
+ * source code.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor);
+
+/**
+ * \brief Retrieve the physical extent of the source construct referenced by
+ * the given cursor.
+ *
+ * The extent of a cursor starts with the file/line/column pointing at the
+ * first character within the source construct that the cursor refers to and
+ * ends with the last character withinin that source construct. For a
+ * declaration, the extent covers the declaration itself. For a reference,
+ * the extent covers the location of the reference (e.g., where the referenced
+ * entity was actually used).
+ */
+CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
-CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor);
-CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor);
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CURSOR_TRAVERSAL Traversing the AST with cursors
+ *
+ * These routines provide the ability to traverse the abstract syntax tree
+ * using cursors.
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes how the traversal of the children of a particular
+ * cursor should proceed after visiting a particular child cursor.
+ *
+ * A value of this enumeration type should be returned by each
+ * \c CXCursorVisitor to indicate how clang_visitChildren() proceed.
+ */
+enum CXChildVisitResult {
+ /**
+ * \brief Terminates the cursor traversal.
+ */
+ CXChildVisit_Break,
+ /**
+ * \brief Continues the cursor traversal with the next sibling of
+ * the cursor just visited, without visiting its children.
+ */
+ CXChildVisit_Continue,
+ /**
+ * \brief Recursively traverse the children of this cursor, using
+ * the same visitor and client data.
+ */
+ CXChildVisit_Recurse
+};
+
+/**
+ * \brief Visitor invoked for each cursor found by a traversal.
+ *
+ * This visitor function will be invoked for each cursor found by
+ * clang_visitCursorChildren(). Its first argument is the cursor being
+ * visited, its second argument is the parent visitor for that cursor,
+ * and its third argument is the client data provided to
+ * clang_visitCursorChildren().
+ *
+ * The visitor should return one of the \c CXChildVisitResult values
+ * to direct clang_visitCursorChildren().
+ */
+typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data);
+
+/**
+ * \brief Visit the children of a particular cursor.
+ *
+ * This function visits all the direct children of the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited child. The traversal may be recursive, if the visitor returns
+ * \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if
+ * the visitor returns \c CXChildVisit_Break.
+ *
+ * \param tu the translation unit into which the cursor refers.
+ *
+ * \param parent the cursor whose child may be visited. All kinds of
+ * cursors can be visited, including invalid visitors (which, by
+ * definition, have no children).
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * child of \p parent.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the visitor each time it is invoked.
+ *
+ * \returns a non-zero value if the traversal was terminated
+ * prematurely by the visitor returning \c CXChildVisit_Break.
+ */
+CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
+ CXCursorVisitor visitor,
+ CXClientData client_data);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CURSOR_XREF Cross-referencing in the AST
+ *
+ * These routines provide the ability to determine references within and
+ * across translation units, by providing the names of the entities referenced
+ * by cursors, follow reference cursors to the declarations they reference,
+ * and associate declarations with their definitions.
+ *
+ * @{
+ */
+
+/**
+ * \brief Retrieve a Unified Symbol Resolution (USR) for the entity referenced
+ * by the given cursor.
+ *
+ * A Unified Symbol Resolution (USR) is a string that identifies a particular
+ * entity (function, class, variable, etc.) within a program. USRs can be
+ * compared across translation units to determine, e.g., when references in
+ * one translation refer to an entity defined in another translation unit.
+ */
+CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor);
+
+/**
+ * \brief Retrieve a name for the entity referenced by this cursor.
+ */
CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
-CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */
-CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor);
+/** \brief For a cursor that is a reference, retrieve a cursor representing the
+ * entity that it references.
+ *
+ * Reference cursors refer to other entities in the AST. For example, an
+ * Objective-C superclass reference cursor refers to an Objective-C class.
+ * This function produces the cursor for the Objective-C class from the
+ * cursor for the superclass reference. If the input cursor is a declaration or
+ * definition, it returns that declaration or definition unchanged.
+ * Othewise, returns the NULL cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor);
+
+/**
+ * \brief For a cursor that is either a reference to or a declaration
+ * of some entity, retrieve a cursor that describes the definition of
+ * that entity.
+ *
+ * Some entities can be declared multiple times within a translation
+ * unit, but only one of those declarations can also be a
+ * definition. For example, given:
+ *
+ * \code
+ * int f(int, int);
+ * int g(int x, int y) { return f(x, y); }
+ * int f(int a, int b) { return a + b; }
+ * int f(int, int);
+ * \endcode
+ *
+ * there are three declarations of the function "f", but only the
+ * second one is a definition. The clang_getCursorDefinition()
+ * function will take any cursor pointing to a declaration of "f"
+ * (the first or fourth lines of the example) or a cursor referenced
+ * that uses "f" (the call to "f' inside "g") and will return a
+ * declaration cursor pointing to the definition (the second "f"
+ * declaration).
+ *
+ * If given a cursor for which there is no corresponding definition,
+ * e.g., because there is no definition of that entity within this
+ * translation unit, returns a NULL cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursorDefinition(CXCursor);
+
+/**
+ * \brief Determine whether the declaration pointed to by this cursor
+ * is also a definition of that entity.
+ */
+CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_DEBUG Debugging facilities
+ *
+ * These routines are used for testing and debugging, only, and should not
+ * be relied upon.
+ *
+ * @{
+ */
+
/* for debug/testing */
CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
@@ -396,13 +858,22 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
unsigned *endLine,
unsigned *endColumn);
-/*
- * If CXCursorKind == Cursor_Reference, then this will return the referenced
- * declaration.
- * If CXCursorKind == Cursor_Declaration, then this will return the declaration.
+/**
+ * @}
*/
-CINDEX_LINKAGE CXDecl clang_getCursorDecl(CXCursor);
-
+
+/**
+ * \defgroup CINDEX_CODE_COMPLET Code completion
+ *
+ * Code completion involves taking an (incomplete) source file, along with
+ * knowledge of where the user is actively editing that file, and suggesting
+ * syntactically- and semantically-valid constructs that the user might want to
+ * use at that particular point in the source code. These data structures and
+ * routines provide support for code completion.
+ *
+ * @{
+ */
+
/**
* \brief A semantic string that describes a code-completion result.
*
@@ -771,6 +1242,27 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
CINDEX_LINKAGE
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
+/**
+ * @}
+ */
+
+
+/**
+ * \defgroup CINDEX_MISC Miscellaneous utility functions
+ *
+ * @{
+ */
+
+CINDEX_LINKAGE const char *clang_getClangVersion();
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 5db8e20e7e48..e5429bec143c 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -61,6 +61,7 @@ namespace clang {
class TypedefDecl;
class UsingDecl;
class UsingShadowDecl;
+ class UnresolvedSetIterator;
namespace Builtin { class Context; }
@@ -397,6 +398,11 @@ public:
/// BlockPointer.
QualType getNoReturnType(QualType T, bool AddNoReturn = true);
+ /// getCallConvType - Adds the specified calling convention attribute to
+ /// the given type, which must be a FunctionType or a pointer to an
+ /// allowable type.
+ QualType getCallConvType(QualType T, CallingConv CallConv);
+
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
@@ -513,7 +519,8 @@ public:
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
- QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false);
+ QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false,
+ CallingConv CallConv = CC_Default);
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
@@ -522,7 +529,8 @@ public:
unsigned TypeQuals, bool hasExceptionSpec = false,
bool hasAnyExceptionSpec = false,
unsigned NumExs = 0, const QualType *ExArray = 0,
- bool NoReturn = false);
+ bool NoReturn = false,
+ CallingConv CallConv = CC_Default);
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.
@@ -746,8 +754,8 @@ public:
DeclarationName getNameForTemplate(TemplateName Name);
- TemplateName getOverloadedTemplateName(NamedDecl * const *Begin,
- NamedDecl * const *End);
+ TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 7c826fe75d11..1491b1edbbac 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -65,9 +65,21 @@ struct CXXBasePathElement {
/// subobject is being used.
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
public:
+ CXXBasePath() : Access(AS_public) {}
+
+ /// \brief The access along this inheritance path. This is only
+ /// calculated when recording paths. AS_none is a special value
+ /// used to indicate a path which permits no legal access.
+ AccessSpecifier Access;
+
/// \brief The set of declarations found inside this base class
/// subobject.
DeclContext::lookup_result Decls;
+
+ void clear() {
+ llvm::SmallVectorImpl<CXXBasePathElement>::clear();
+ Access = AS_public;
+ }
};
/// BasePaths - Represents the set of paths from a derived class to
@@ -131,10 +143,10 @@ class CXXBasePaths {
/// is also recorded.
bool DetectVirtual;
- /// ScratchPath - A BasePath that is used by Sema::IsDerivedFrom
+ /// ScratchPath - A BasePath that is used by Sema::lookupInBases
/// to help build the set of paths.
CXXBasePath ScratchPath;
-
+
/// DetectedVirtual - The base class that is virtual.
const RecordType *DetectedVirtual;
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 21b59099138a..6d52b2b2bc91 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -55,32 +55,6 @@ public:
TypeLoc getTypeLoc() const;
};
-/// UnresolvedSet - A set of unresolved declarations. This is needed
-/// in a lot of places, but isn't really worth breaking into its own
-/// header right now.
-class UnresolvedSet {
- typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
- DeclsTy Decls;
-
-public:
- void addDecl(NamedDecl *D) {
- Decls.push_back(D);
- }
-
- bool replace(const NamedDecl* Old, NamedDecl *New) {
- for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I)
- if (*I == Old)
- return (*I = New, true);
- return false;
- }
-
- unsigned size() const { return Decls.size(); }
-
- typedef DeclsTy::const_iterator iterator;
- iterator begin() const { return Decls.begin(); }
- iterator end() const { return Decls.end(); }
-};
-
/// TranslationUnitDecl - The top declaration context.
class TranslationUnitDecl : public Decl, public DeclContext {
ASTContext &Ctx;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 497f86347a86..775bce2a15fc 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -16,8 +16,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Type.h"
-// FIXME: Layering violation
-#include "clang/Parse/AccessSpecifier.h"
+#include "clang/Basic/Specifiers.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/ADT/PointerUnion.h"
@@ -1017,13 +1016,8 @@ private:
};
inline bool Decl::isTemplateParameter() const {
- return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm;
-}
-
-inline bool Decl::isDefinedOutsideFunctionOrMethod() const {
- if (getDeclContext())
- return !getDeclContext()->getLookupContext()->isFunctionOrMethod();
- return true;
+ return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm ||
+ getKind() == TemplateTemplateParm;
}
} // end clang.
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 336a895de8cf..73ebf52d383b 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -16,6 +16,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/UnresolvedSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -275,13 +276,13 @@ class CXXRecordDecl : public RecordDecl {
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
/// CXXConversionDecl.
- UnresolvedSet Conversions;
+ UnresolvedSet<4> Conversions;
/// VisibleConversions - Overload set containing the conversion functions
/// of this C++ class and all those inherited conversion functions that
/// are visible in this class. Each of the entries in this overload set is
/// a CXXConversionDecl or a FunctionTemplateDecl.
- UnresolvedSet VisibleConversions;
+ UnresolvedSet<4> VisibleConversions;
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
@@ -483,20 +484,20 @@ public:
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
- UnresolvedSet *getConversionFunctions() {
+ UnresolvedSetImpl *getConversionFunctions() {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
- const UnresolvedSet *getConversionFunctions() const {
+ const UnresolvedSetImpl *getConversionFunctions() const {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
- typedef UnresolvedSet::iterator conversion_iterator;
+ typedef UnresolvedSetImpl::iterator conversion_iterator;
conversion_iterator conversion_begin() const { return Conversions.begin(); }
conversion_iterator conversion_end() const { return Conversions.end(); }
@@ -509,7 +510,7 @@ public:
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
- const UnresolvedSet *getVisibleConversionFunctions();
+ const UnresolvedSetImpl *getVisibleConversionFunctions();
/// addVisibleConversionFunction - Add a new conversion function to the
/// list of visible conversion functions.
@@ -816,6 +817,15 @@ public:
/// GraphViz.
void viewInheritance(ASTContext& Context) const;
+ /// MergeAccess - Calculates the access of a decl that is reached
+ /// along a path.
+ static AccessSpecifier MergeAccess(AccessSpecifier PathAccess,
+ AccessSpecifier DeclAccess) {
+ assert(DeclAccess != AS_none);
+ if (DeclAccess == AS_private) return AS_none;
+ return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
+ }
+
static bool classof(const Decl *D) {
return D->getKind() == CXXRecord ||
D->getKind() == ClassTemplateSpecialization ||
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 920d31fc7ce4..0fb0db13bb57 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -75,6 +75,24 @@ public:
}
};
+/// \brief A list of Objective-C protocols, along with the source
+/// locations at which they were referenced.
+class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
+ SourceLocation *Locations;
+
+ using ObjCList<ObjCProtocolDecl>::set;
+
+public:
+ ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(0) { }
+
+ typedef const SourceLocation *loc_iterator;
+ loc_iterator loc_begin() const { return Locations; }
+ loc_iterator loc_end() const { return Locations + size(); }
+
+ void set(ObjCProtocolDecl* const* InList, unsigned Elts,
+ const SourceLocation *Locs, ASTContext &Ctx);
+ void Destroy(ASTContext &Ctx);
+};
/// ObjCMethodDecl - Represents an instance or class method declaration.
@@ -410,9 +428,9 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCInterfaceDecl *SuperClass;
/// Protocols referenced in interface header declaration
- ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+ ObjCProtocolList ReferencedProtocols;
- /// Instance variables in the interface.
+ /// Instance variables in the interface. This list is completely redundant.
ObjCList<ObjCIvarDecl> IVars;
/// List of categories defined for this class.
@@ -442,7 +460,7 @@ public:
SourceLocation ClassLoc = SourceLocation(),
bool ForwardDecl = false,
bool isInternal = false);
- const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+ const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
@@ -459,9 +477,16 @@ public:
: getClassMethod(Sel);
}
- typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ protocol_loc_iterator protocol_loc_begin() const {
+ return ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ return ReferencedProtocols.loc_end();
+ }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
typedef ObjCList<ObjCIvarDecl>::iterator ivar_iterator;
@@ -473,14 +498,16 @@ public:
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
- ASTContext &C) {
- ReferencedProtocols.set(List, Num, C);
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
}
/// mergeClassExtensionProtocolList - Merge class extension's protocol list
/// into the protocol list for this class.
- void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
- ASTContext &C);
+ void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
+ unsigned Num,
+ const SourceLocation *Locs,
+ ASTContext &C);
void setIVarList(ObjCIvarDecl * const *List, unsigned Num, ASTContext &C) {
IVars.set(List, Num, C);
@@ -660,7 +687,7 @@ public:
///
class ObjCProtocolDecl : public ObjCContainerDecl {
/// Referenced protocols
- ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+ ObjCProtocolList ReferencedProtocols;
bool isForwardProtoDecl; // declared with @protocol.
@@ -680,19 +707,26 @@ public:
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
- const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+ const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
- typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ protocol_loc_iterator protocol_loc_begin() const {
+ return ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ return ReferencedProtocols.loc_end();
+ }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
- ASTContext &C) {
- ReferencedProtocols.set(List, Num, C);
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
}
ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
@@ -772,31 +806,45 @@ public:
/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
///
class ObjCForwardProtocolDecl : public Decl {
- ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+ ObjCProtocolList ReferencedProtocols;
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts,
- ASTContext &C);
+ const SourceLocation *Locs, ASTContext &C);
virtual ~ObjCForwardProtocolDecl() {}
public:
static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
- ObjCProtocolDecl *const *Elts = 0,
- unsigned Num = 0);
+ ObjCProtocolDecl *const *Elts,
+ unsigned Num,
+ const SourceLocation *Locs);
+
+ static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L) {
+ return Create(C, DC, L, 0, 0, 0);
+ }
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
- typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ protocol_loc_iterator protocol_loc_begin() const {
+ return ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ return ReferencedProtocols.loc_end();
+ }
+
unsigned protocol_size() const { return ReferencedProtocols.size(); }
/// setProtocolList - Set the list of forward protocols.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
- ASTContext &C) {
- ReferencedProtocols.set(List, Num, C);
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
}
static bool classof(const Decl *D) {
return D->getKind() == ObjCForwardProtocol;
@@ -826,22 +874,32 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
ObjCInterfaceDecl *ClassInterface;
/// referenced protocols in this category.
- ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+ ObjCProtocolList ReferencedProtocols;
/// Next category belonging to this class.
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory;
- SourceLocation EndLoc; // marks the '>' or identifier.
+ /// \brief The location of the '@' in '@interface'
+ SourceLocation AtLoc;
- ObjCCategoryDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
- : ObjCContainerDecl(ObjCCategory, DC, L, Id),
- ClassInterface(0), NextClassCategory(0){
+ /// \brief The location of the category name in this declaration.
+ SourceLocation CategoryNameLoc;
+
+ ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
+ SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id)
+ : ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
+ ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc),
+ CategoryNameLoc(CategoryNameLoc) {
}
public:
static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id);
+ SourceLocation AtLoc,
+ SourceLocation ClassNameLoc,
+ SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id);
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
@@ -853,18 +911,25 @@ public:
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
- ASTContext &C) {
- ReferencedProtocols.set(List, Num, C);
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
}
- const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+ const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
- typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ protocol_loc_iterator protocol_loc_begin() const {
+ return ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ return ReferencedProtocols.loc_end();
+ }
ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
void setNextClassCategory(ObjCCategoryDecl *Cat) {
@@ -874,10 +939,16 @@ public:
NextClassCategory = ClassInterface->getCategoryList();
ClassInterface->setCategoryList(this);
}
- // Location information, modeled after the Stmt API.
- SourceLocation getLocStart() const { return getLocation(); } // '@'interface
- SourceLocation getLocEnd() const { return EndLoc; }
- void setLocEnd(SourceLocation LE) { EndLoc = LE; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation At) { AtLoc = At; }
+
+ SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
+ void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, getAtEndRange().getEnd());
+ }
static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; }
static bool classof(const ObjCCategoryDecl *D) { return true; }
@@ -1133,6 +1204,7 @@ public:
enum SetterKind { Assign, Retain, Copy };
enum PropertyControl { None, Required, Optional };
private:
+ SourceLocation AtLoc; // location of @property
QualType DeclType;
unsigned PropertyAttributes : 8;
@@ -1147,8 +1219,8 @@ private:
ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
- QualType T)
- : NamedDecl(ObjCProperty, DC, L, Id), DeclType(T),
+ SourceLocation AtLocation, QualType T)
+ : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), DeclType(T),
PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None),
GetterName(Selector()),
SetterName(Selector()),
@@ -1156,8 +1228,12 @@ private:
public:
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
- IdentifierInfo *Id, QualType T,
+ IdentifierInfo *Id, SourceLocation AtLocation,
+ QualType T,
PropertyControl propControl = None);
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+
QualType getType() const { return DeclType; }
void setType(QualType T) { DeclType = T; }
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index cfbae9fb2cbf..252781767169 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1462,14 +1462,19 @@ class CompoundLiteralExpr : public Expr {
/// compound literal like "(int){4}". This can be null if this is a
/// synthesized compound expression.
SourceLocation LParenLoc;
+
+ /// The type as written. This can be an incomplete array type, in
+ /// which case the actual expression type will be different.
+ TypeSourceInfo *TInfo;
Stmt *Init;
bool FileScope;
public:
// FIXME: Can compound literals be value-dependent?
- CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init,
- bool fileScope)
- : Expr(CompoundLiteralExprClass, ty, ty->isDependentType(), false),
- LParenLoc(lparenloc), Init(init), FileScope(fileScope) {}
+ CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
+ QualType T, Expr *init, bool fileScope)
+ : Expr(CompoundLiteralExprClass, T,
+ tinfo->getType()->isDependentType(), false),
+ LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {}
/// \brief Construct an empty compound literal.
explicit CompoundLiteralExpr(EmptyShell Empty)
@@ -1485,6 +1490,9 @@ public:
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+ TypeSourceInfo *getTypeSourceInfo() const { return TInfo; }
+ void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; }
+
virtual SourceRange getSourceRange() const {
// FIXME: Init should never be null.
if (!Init)
@@ -1712,24 +1720,28 @@ public:
/// expression will be an lvalue. The reference type, however, will
/// not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
- /// TypeAsWritten - The type that this expression is casting to, as
- /// written in the source code.
- QualType TypeAsWritten;
+ /// TInfo - Source type info for the (written) type
+ /// this expression is casting to.
+ TypeSourceInfo *TInfo;
protected:
ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
- Expr *op, QualType writtenTy)
- : CastExpr(SC, exprTy, kind, op), TypeAsWritten(writtenTy) {}
+ Expr *op, TypeSourceInfo *writtenTy)
+ : CastExpr(SC, exprTy, kind, op), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
: CastExpr(SC, Shell) { }
public:
+ /// getTypeInfoAsWritten - Returns the type source info for the type
+ /// that this expression is casting to.
+ TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; }
+ void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; }
+
/// getTypeAsWritten - Returns the type that this expression is
/// casting to, as written in the source code.
- QualType getTypeAsWritten() const { return TypeAsWritten; }
- void setTypeAsWritten(QualType T) { TypeAsWritten = T; }
+ QualType getTypeAsWritten() const { return TInfo->getType(); }
static bool classof(const Stmt *T) {
StmtClass SC = T->getStmtClass();
@@ -1750,8 +1762,9 @@ class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
public:
- CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, QualType writtenTy,
- SourceLocation l, SourceLocation r) :
+ CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op,
+ TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation r) :
ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, writtenTy),
LPLoc(l), RPLoc(r) {}
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 55d5108e6174..6ce95ac5227f 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -16,7 +16,7 @@
#include "clang/Basic/TypeTraits.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/Decl.h"
+#include "clang/AST/UnresolvedSet.h"
#include "clang/AST/TemplateBase.h"
namespace clang {
@@ -118,9 +118,12 @@ private:
protected:
CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
- QualType writtenTy, SourceLocation l)
+ TypeSourceInfo *writtenTy, SourceLocation l)
: ExplicitCastExpr(SC, ty, kind, op, writtenTy), Loc(l) {}
+ explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell)
+ : ExplicitCastExpr(SC, Shell) { }
+
public:
const char *getCastName() const;
@@ -154,9 +157,12 @@ public:
class CXXStaticCastExpr : public CXXNamedCastExpr {
public:
CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
- QualType writtenTy, SourceLocation l)
+ TypeSourceInfo *writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, writtenTy, l) {}
+ explicit CXXStaticCastExpr(EmptyShell Empty)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
}
@@ -171,10 +177,13 @@ public:
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
public:
- CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, QualType writtenTy,
- SourceLocation l)
+ CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
+ TypeSourceInfo *writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, writtenTy, l) {}
+ explicit CXXDynamicCastExpr(EmptyShell Empty)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
}
@@ -190,10 +199,13 @@ public:
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
public:
CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
- QualType writtenTy, SourceLocation l)
+ TypeSourceInfo *writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op,
writtenTy, l) {}
+ explicit CXXReinterpretCastExpr(EmptyShell Empty)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
}
@@ -207,10 +219,13 @@ public:
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
public:
- CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy,
+ CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
SourceLocation l)
: CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, writtenTy, l) {}
+ explicit CXXConstCastExpr(EmptyShell Empty)
+ : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
}
@@ -625,15 +640,20 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
- CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
+ CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
Expr *castExpr, SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+ explicit CXXFunctionalCastExpr(EmptyShell Shell)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { }
+
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
+ void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
@@ -1052,7 +1072,7 @@ public:
class UnresolvedLookupExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
- UnresolvedSet Results;
+ UnresolvedSet<4> Results;
/// The name declared.
DeclarationName Name;
@@ -1113,15 +1133,15 @@ public:
/// Computes whether an unresolved lookup on the given declarations
/// and optional template arguments is type- and value-dependent.
- static bool ComputeDependence(NamedDecl * const *Begin,
- NamedDecl * const *End,
+ static bool ComputeDependence(UnresolvedSetImpl::const_iterator Begin,
+ UnresolvedSetImpl::const_iterator End,
const TemplateArgumentListInfo *Args);
void addDecl(NamedDecl *Decl) {
Results.addDecl(Decl);
}
- typedef UnresolvedSet::iterator decls_iterator;
+ typedef UnresolvedSetImpl::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
@@ -1696,7 +1716,7 @@ public:
class UnresolvedMemberExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
- UnresolvedSet Results;
+ UnresolvedSet<4> Results;
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. This can be null if this is an 'unbased'
@@ -1775,7 +1795,7 @@ public:
Results.addDecl(Decl);
}
- typedef UnresolvedSet::iterator decls_iterator;
+ typedef UnresolvedSetImpl::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 9b0cdc3a52e6..b7b60df5acb4 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -385,6 +385,14 @@ public:
}
};
+/// CallingConv - Specifies the calling convention that a function uses.
+enum CallingConv {
+ CC_Default,
+ CC_C, // __attribute__((cdecl))
+ CC_X86StdCall, // __attribute__((stdcall))
+ CC_X86FastCall // __attribute__((fastcall))
+};
+
/// QualType - For efficiency, we don't store CV-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
@@ -669,6 +677,10 @@ public:
/// false otherwise.
bool getNoReturnAttr() const;
+ /// getCallConv - Returns the calling convention of the type if the type
+ /// is a function type, CC_Default otherwise.
+ CallingConv getCallConv() const;
+
private:
// These methods are implemented in a separate translation unit;
// "static"-ize them to avoid creating temporary QualTypes in the
@@ -1691,21 +1703,25 @@ class FunctionType : public Type {
/// NoReturn - Indicates if the function type is attribute noreturn.
unsigned NoReturn : 1;
+ /// CallConv - The calling convention used by the function.
+ unsigned CallConv : 2;
+
// The type returned by the function.
QualType ResultType;
protected:
FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
unsigned typeQuals, QualType Canonical, bool Dependent,
- bool noReturn = false)
+ bool noReturn = false, CallingConv callConv = CC_Default)
: Type(tc, Canonical, Dependent),
SubClassData(SubclassInfo), TypeQuals(typeQuals), NoReturn(noReturn),
- ResultType(res) {}
+ CallConv(callConv), ResultType(res) {}
bool getSubClassData() const { return SubClassData; }
unsigned getTypeQuals() const { return TypeQuals; }
public:
QualType getResultType() const { return ResultType; }
bool getNoReturnAttr() const { return NoReturn; }
+ CallingConv getCallConv() const { return (CallingConv)CallConv; }
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionNoProto ||
@@ -1718,9 +1734,9 @@ public:
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionNoProtoType(QualType Result, QualType Canonical,
- bool NoReturn = false)
+ bool NoReturn = false, CallingConv CallConv = CC_Default)
: FunctionType(FunctionNoProto, Result, false, 0, Canonical,
- /*Dependent=*/false, NoReturn) {}
+ /*Dependent=*/false, NoReturn, CallConv) {}
friend class ASTContext; // ASTContext creates these.
public:
// No additional state past what FunctionType provides.
@@ -1762,10 +1778,12 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
bool isVariadic, unsigned typeQuals, bool hasExs,
bool hasAnyExs, const QualType *ExArray,
- unsigned numExs, QualType Canonical, bool NoReturn)
+ unsigned numExs, QualType Canonical, bool NoReturn,
+ CallingConv CallConv)
: FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
(Result->isDependentType() ||
- hasAnyDependentType(ArgArray, numArgs)), NoReturn),
+ hasAnyDependentType(ArgArray, numArgs)), NoReturn,
+ CallConv),
NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
AnyExceptionSpec(hasAnyExs) {
// Fill in the trailing argument array.
@@ -2496,26 +2514,31 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {
// List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is enterred more than once.
- llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols;
+ ObjCProtocolDecl **Protocols;
+ unsigned NumProtocols;
- ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D,
- ObjCProtocolDecl **Protos, unsigned NumP) :
- Type(ObjCInterface, Canonical, /*Dependent=*/false),
- Decl(D), Protocols(Protos, Protos+NumP) { }
+ ObjCInterfaceType(ASTContext &Ctx, QualType Canonical, ObjCInterfaceDecl *D,
+ ObjCProtocolDecl **Protos, unsigned NumP);
friend class ASTContext; // ASTContext creates these.
public:
+ void Destroy(ASTContext& C);
+
ObjCInterfaceDecl *getDecl() const { return Decl; }
/// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none.
- unsigned getNumProtocols() const { return Protocols.size(); }
+ unsigned getNumProtocols() const { return NumProtocols; }
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface.
- typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
- qual_iterator qual_begin() const { return Protocols.begin(); }
- qual_iterator qual_end() const { return Protocols.end(); }
- bool qual_empty() const { return Protocols.size() == 0; }
+ typedef ObjCProtocolDecl* const * qual_iterator;
+ qual_iterator qual_begin() const {
+ return Protocols;
+ }
+ qual_iterator qual_end() const {
+ return Protocols ? Protocols + NumProtocols : 0;
+ }
+ bool qual_empty() const { return NumProtocols == 0; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2541,15 +2564,16 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
// List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is entered more than once.
- llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
+ ObjCProtocolDecl **Protocols;
+ unsigned NumProtocols;
- ObjCObjectPointerType(QualType Canonical, QualType T,
- ObjCProtocolDecl **Protos, unsigned NumP) :
- Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
- PointeeType(T), Protocols(Protos, Protos+NumP) { }
+ ObjCObjectPointerType(ASTContext &Ctx, QualType Canonical, QualType T,
+ ObjCProtocolDecl **Protos, unsigned NumP);
friend class ASTContext; // ASTContext creates these.
public:
+ void Destroy(ASTContext& C);
+
// Get the pointee type. Pointee will either be:
// - a built-in type (for 'id' and 'Class').
// - an interface type (for user-defined types).
@@ -2567,35 +2591,39 @@ public:
/// isObjCIdType - true for "id".
bool isObjCIdType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
- !Protocols.size();
+ !NumProtocols;
}
/// isObjCClassType - true for "Class".
bool isObjCClassType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
- !Protocols.size();
+ !NumProtocols;
}
/// isObjCQualifiedIdType - true for "id <p>".
bool isObjCQualifiedIdType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
- Protocols.size();
+ NumProtocols;
}
/// isObjCQualifiedClassType - true for "Class <p>".
bool isObjCQualifiedClassType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
- Protocols.size();
+ NumProtocols;
}
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface.
- typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
+ typedef ObjCProtocolDecl* const * qual_iterator;
- qual_iterator qual_begin() const { return Protocols.begin(); }
- qual_iterator qual_end() const { return Protocols.end(); }
- bool qual_empty() const { return Protocols.size() == 0; }
+ qual_iterator qual_begin() const {
+ return Protocols;
+ }
+ qual_iterator qual_end() const {
+ return Protocols ? Protocols + NumProtocols : NULL;
+ }
+ bool qual_empty() const { return NumProtocols == 0; }
/// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none.
- unsigned getNumProtocols() const { return Protocols.size(); }
+ unsigned getNumProtocols() const { return NumProtocols; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2797,6 +2825,26 @@ inline bool QualType::getNoReturnAttr() const {
return false;
}
+/// getCallConv - Returns the calling convention of the type if the type
+/// is a function type, CC_Default otherwise.
+inline CallingConv QualType::getCallConv() const {
+ if (const PointerType *PT = getTypePtr()->getAs<PointerType>())
+ return PT->getPointeeType().getCallConv();
+ else if (const ReferenceType *RT = getTypePtr()->getAs<ReferenceType>())
+ return RT->getPointeeType().getCallConv();
+ else if (const MemberPointerType *MPT =
+ getTypePtr()->getAs<MemberPointerType>())
+ return MPT->getPointeeType().getCallConv();
+ else if (const BlockPointerType *BPT =
+ getTypePtr()->getAs<BlockPointerType>()) {
+ if (const FunctionType *FT = BPT->getPointeeType()->getAs<FunctionType>())
+ return FT->getCallConv();
+ } else if (const FunctionType *FT = getTypePtr()->getAs<FunctionType>())
+ return FT->getCallConv();
+
+ return CC_Default;
+}
+
/// isMoreQualifiedThan - Determine whether this type is more
/// qualified than the Other type. For example, "const volatile int"
/// is more qualified than "const int", "volatile int", and
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index c36c0ffde32e..6fb51edb76f9 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -16,6 +16,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/Basic/Specifiers.h"
namespace clang {
class ParmVarDecl;
@@ -372,6 +373,111 @@ public:
};
+struct BuiltinLocInfo {
+ SourceLocation BuiltinLoc;
+};
+
+/// \brief Wrapper for source info for builtin types.
+class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ BuiltinTypeLoc,
+ BuiltinType,
+ BuiltinLocInfo> {
+public:
+ enum { LocalDataSize = sizeof(BuiltinLocInfo) };
+
+ SourceLocation getBuiltinLoc() const {
+ return getLocalData()->BuiltinLoc;
+ }
+ void setBuiltinLoc(SourceLocation Loc) {
+ getLocalData()->BuiltinLoc = Loc;
+ }
+
+ SourceLocation getNameLoc() const { return getBuiltinLoc(); }
+
+ WrittenBuiltinSpecs& getWrittenBuiltinSpecs() {
+ return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
+ }
+ const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
+ return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
+ }
+
+ bool needsExtraLocalData() const {
+ BuiltinType::Kind bk = getTypePtr()->getKind();
+ return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128)
+ || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble)
+ || bk == BuiltinType::UChar
+ || bk == BuiltinType::SChar;
+ }
+
+ unsigned getExtraLocalDataSize() const {
+ return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getBuiltinLoc(), getBuiltinLoc());
+ }
+
+ TypeSpecifierSign getWrittenSignSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign);
+ else
+ return TSS_unspecified;
+ }
+ bool hasWrittenSignSpec() const {
+ return getWrittenSignSpec() != TSS_unspecified;
+ }
+ void setWrittenSignSpec(TypeSpecifierSign written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().Sign = written;
+ }
+
+ TypeSpecifierWidth getWrittenWidthSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width);
+ else
+ return TSW_unspecified;
+ }
+ bool hasWrittenWidthSpec() const {
+ return getWrittenWidthSpec() != TSW_unspecified;
+ }
+ void setWrittenWidthSpec(TypeSpecifierWidth written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().Width = written;
+ }
+
+ TypeSpecifierType getWrittenTypeSpec() const;
+ bool hasWrittenTypeSpec() const {
+ return getWrittenTypeSpec() != TST_unspecified;
+ }
+ void setWrittenTypeSpec(TypeSpecifierType written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().Type = written;
+ }
+
+ bool hasModeAttr() const {
+ if (needsExtraLocalData())
+ return getWrittenBuiltinSpecs().ModeAttr;
+ else
+ return false;
+ }
+ void setModeAttr(bool written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().ModeAttr = written;
+ }
+
+ void initializeLocal(SourceLocation Loc) {
+ setBuiltinLoc(Loc);
+ if (needsExtraLocalData()) {
+ WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs();
+ wbs.Sign = TSS_unspecified;
+ wbs.Width = TSW_unspecified;
+ wbs.Type = TST_unspecified;
+ wbs.ModeAttr = false;
+ }
+ }
+};
+
+
/// \brief Wrapper for source info for typedefs.
class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
TypedefTypeLoc,
@@ -421,12 +527,6 @@ public:
EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
};
-/// \brief Wrapper for source info for builtin types.
-class BuiltinTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
- BuiltinTypeLoc,
- BuiltinType> {
-};
-
/// \brief Wrapper for template type parameters.
class TemplateTypeParmTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h
index 95ec175a53a4..50fc43913f4c 100644
--- a/include/clang/AST/TypeLocVisitor.h
+++ b/include/clang/AST/TypeLocVisitor.h
@@ -43,6 +43,7 @@ public:
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
#include "clang/AST/TypeLocNodes.def"
}
+ llvm_unreachable("unexpected type loc class!");
}
#define TYPELOC(CLASS, PARENT) \
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
new file mode 100644
index 000000000000..055d15264674
--- /dev/null
+++ b/include/clang/AST/UnresolvedSet.h
@@ -0,0 +1,211 @@
+//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the UnresolvedSet class, which is used to store
+// collections of declarations in the AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H
+#define LLVM_CLANG_AST_UNRESOLVEDSET_H
+
+#include <iterator>
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/Basic/Specifiers.h"
+
+namespace clang {
+
+class NamedDecl;
+
+/// The iterator over UnresolvedSets. Serves as both the const and
+/// non-const iterator.
+class UnresolvedSetIterator {
+
+ typedef llvm::PointerIntPair<NamedDecl*, 2> DeclEntry;
+ typedef llvm::SmallVectorImpl<DeclEntry> DeclsTy;
+ typedef DeclsTy::iterator IteratorTy;
+
+ IteratorTy ir;
+
+ friend class UnresolvedSetImpl;
+ explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {}
+ explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) :
+ ir(const_cast<DeclsTy::iterator>(ir)) {}
+public:
+ UnresolvedSetIterator() {}
+
+ typedef std::iterator_traits<IteratorTy>::difference_type difference_type;
+ typedef NamedDecl *value_type;
+ typedef NamedDecl **pointer;
+ typedef NamedDecl *reference;
+ typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
+
+ NamedDecl *getDecl() const { return ir->getPointer(); }
+ AccessSpecifier getAccess() const { return AccessSpecifier(ir->getInt()); }
+
+ NamedDecl *operator*() const { return getDecl(); }
+
+ UnresolvedSetIterator &operator++() { ++ir; return *this; }
+ UnresolvedSetIterator operator++(int) { return UnresolvedSetIterator(ir++); }
+ UnresolvedSetIterator &operator--() { --ir; return *this; }
+ UnresolvedSetIterator operator--(int) { return UnresolvedSetIterator(ir--); }
+
+ UnresolvedSetIterator &operator+=(difference_type d) {
+ ir += d; return *this;
+ }
+ UnresolvedSetIterator operator+(difference_type d) const {
+ return UnresolvedSetIterator(ir + d);
+ }
+ UnresolvedSetIterator &operator-=(difference_type d) {
+ ir -= d; return *this;
+ }
+ UnresolvedSetIterator operator-(difference_type d) const {
+ return UnresolvedSetIterator(ir - d);
+ }
+ value_type operator[](difference_type d) const { return *(*this + d); }
+
+ difference_type operator-(const UnresolvedSetIterator &o) const {
+ return ir - o.ir;
+ }
+
+ bool operator==(const UnresolvedSetIterator &o) const { return ir == o.ir; }
+ bool operator!=(const UnresolvedSetIterator &o) const { return ir != o.ir; }
+ bool operator<(const UnresolvedSetIterator &o) const { return ir < o.ir; }
+ bool operator<=(const UnresolvedSetIterator &o) const { return ir <= o.ir; }
+ bool operator>=(const UnresolvedSetIterator &o) const { return ir >= o.ir; }
+ bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; }
+};
+
+/// UnresolvedSet - A set of unresolved declarations. This is needed
+/// in a lot of places, but isn't really worth breaking into its own
+/// header right now.
+class UnresolvedSetImpl {
+ typedef UnresolvedSetIterator::DeclEntry DeclEntry;
+ typedef UnresolvedSetIterator::DeclsTy DeclsTy;
+
+ // Don't allow direct construction, and only permit subclassing by
+ // UnresolvedSet.
+private:
+ template <unsigned N> friend class UnresolvedSet;
+ UnresolvedSetImpl() {}
+ UnresolvedSetImpl(const UnresolvedSetImpl &) {}
+
+public:
+ // We don't currently support assignment through this iterator, so we might
+ // as well use the same implementation twice.
+ typedef UnresolvedSetIterator iterator;
+ typedef UnresolvedSetIterator const_iterator;
+
+ iterator begin() { return iterator(decls().begin()); }
+ iterator end() { return iterator(decls().end()); }
+
+ const_iterator begin() const { return const_iterator(decls().begin()); }
+ const_iterator end() const { return const_iterator(decls().end()); }
+
+ void addDecl(NamedDecl *D) {
+ addDecl(D, AS_none);
+ }
+
+ void addDecl(NamedDecl *D, AccessSpecifier AS) {
+ decls().push_back(DeclEntry(D, AS));
+ }
+
+ /// Replaces the given declaration with the new one, once.
+ ///
+ /// \return true if the set changed
+ bool replace(const NamedDecl* Old, NamedDecl *New) {
+ for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I)
+ if (I->getPointer() == Old)
+ return (I->setPointer(New), true);
+ return false;
+ }
+
+ /// Replaces the declaration at the given iterator with the new one,
+ /// preserving the original access bits.
+ void replace(iterator I, NamedDecl *New) {
+ I.ir->setPointer(New);
+ }
+
+ void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
+ *I.ir = DeclEntry(New, AS);
+ }
+
+ void erase(iterator I) {
+ *I.ir = decls().back();
+ decls().pop_back();
+ }
+
+ void clear() { decls().clear(); }
+ void set_size(unsigned N) { decls().set_size(N); }
+
+ bool empty() const { return decls().empty(); }
+ unsigned size() const { return decls().size(); }
+
+ void append(iterator I, iterator E) {
+ decls().append(I.ir, E.ir);
+ }
+
+ /// A proxy reference for implementing operator[].
+ class Proxy {
+ DeclEntry &Ref;
+
+ friend class UnresolvedSetImpl;
+ Proxy(DeclEntry &Ref) : Ref(Ref) {}
+
+ public:
+ NamedDecl *getDecl() const { return Ref.getPointer(); }
+ void setDecl(NamedDecl *D) { Ref.setPointer(D); }
+
+ AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); }
+ void setAccess(AccessSpecifier AS) const { Ref.setInt(AS); }
+
+ NamedDecl* operator->() const { return getDecl(); }
+ operator NamedDecl*() const { return getDecl(); }
+ Proxy &operator=(const Proxy &D) { Ref = D.Ref; return *this; }
+ };
+ Proxy operator[](unsigned I) { return Proxy(decls()[I]); }
+
+ /// A proxy reference for implementing operator[] const.
+ class ConstProxy {
+ const DeclEntry &Ref;
+
+ friend class UnresolvedSetImpl;
+ ConstProxy(const DeclEntry &Ref) : Ref(Ref) {}
+
+ public:
+ NamedDecl *getDecl() const { return Ref.getPointer(); }
+ AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); }
+
+ NamedDecl *operator->() const { return getDecl(); }
+ operator NamedDecl*() const { return getDecl(); }
+ };
+ ConstProxy operator[](unsigned I) const { return ConstProxy(decls()[I]); }
+
+private:
+ // These work because the only permitted subclass is UnresolvedSetImpl
+
+ DeclsTy &decls() {
+ return *reinterpret_cast<DeclsTy*>(this);
+ }
+ const DeclsTy &decls() const {
+ return *reinterpret_cast<const DeclsTy*>(this);
+ }
+};
+
+/// A set of unresolved declarations
+template <unsigned InlineCapacity> class UnresolvedSet :
+ public UnresolvedSetImpl {
+ llvm::SmallVector<UnresolvedSetImpl::DeclEntry, InlineCapacity> Decls;
+};
+
+
+} // namespace clang
+
+#endif
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 38d4bdfcfced..e87784fd85e1 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -20,12 +20,14 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/SourceLocation.h"
#include <cassert>
namespace llvm {
class raw_ostream;
}
namespace clang {
+ class Decl;
class Stmt;
class Expr;
class CFG;
@@ -33,15 +35,39 @@ namespace clang {
class LangOptions;
class ASTContext;
+namespace {
+// An element of the CFG for implicit descructor calls implied by the language
+// rules.
+class Dtor {
+ // Statement that introduces the variable.
+ Stmt *S;
+ // A token which ends the scope, return, goto, throw, }.
+ SourceLocation Loc;
+public:
+ Dtor(Stmt *s, SourceLocation l) : S(s), Loc(l) {
+ }
+ SourceLocation getLoc() { return Loc; }
+ Stmt *getStmt() { return S; }
+};
+}
+
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
- llvm::PointerIntPair<Stmt *, 1> Data;
+ llvm::PointerIntPair<Stmt *, 2> Data;
public:
+ enum Type { StartScope, EndScope };
explicit CFGElement() {}
CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
+ CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {}
+ // CFGElement(Dtor *S, Type t) : Data(reinterpret_cast<Stmt*>(S), 4) {}
Stmt *getStmt() const { return Data.getPointer(); }
bool asLValue() const { return Data.getInt() == 1; }
+ bool asStartScope() const { return Data.getInt() == 2; }
+ bool asEndScope() const { return Data.getInt() == 3; }
+ bool asDtor() const { return Data.getInt() == 4; }
operator Stmt*() const { return getStmt(); }
+ operator bool() const { return getStmt() != 0; }
+ operator Dtor*() const { return reinterpret_cast<Dtor*>(getStmt()); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
@@ -107,7 +133,7 @@ class CFGBlock {
/// Label - An (optional) label that prefixes the executable
/// statements in the block. When this variable is non-NULL, it is
- /// either an instance of LabelStmt or SwitchCase.
+ /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
Stmt *Label;
/// Terminator - The terminator for a basic block that
@@ -236,6 +262,12 @@ public:
void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) {
Stmts.push_back(CFGElement(Statement, asLValue), C);
}
+ void StartScope(Stmt* S, BumpVectorContext &C) {
+ Stmts.push_back(CFGElement(S, CFGElement::StartScope), C);
+ }
+ void EndScope(Stmt* S, BumpVectorContext &C) {
+ Stmts.push_back(CFGElement(S, CFGElement::EndScope), C);
+ }
};
@@ -254,7 +286,9 @@ public:
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
- static CFG* buildCFG(Stmt* AST, ASTContext *C);
+ static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
+ bool AddEHEdges = false,
+ bool AddScopes = false);
/// createBlock - Create a new block in the CFG. The CFG owns the block;
/// the caller should not directly free it.
diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h
index 63ba558e3d5c..c82bb962fd18 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisContext.h
+++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h
@@ -46,14 +46,21 @@ class AnalysisContext {
ParentMap *PM;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
+ bool AddEHEdges;
public:
- AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0),
- ReferencedBlockVars(0) {}
+ AnalysisContext(const Decl *d, bool addehedges = false)
+ : D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0),
+ AddEHEdges(addehedges) {}
~AnalysisContext();
ASTContext &getASTContext() { return D->getASTContext(); }
const Decl *getDecl() { return D; }
+ /// getAddEHEdges - Return true iff we are adding exceptional edges from
+ /// callExprs. If this is false, then try/catch statements and blocks
+ /// reachable from them can appear to be dead in the CFG, analysis passes must
+ /// cope with that.
+ bool getAddEHEdges() const { return AddEHEdges; }
Stmt *getBody();
CFG *getCFG();
ParentMap &getParentMap();
diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Analysis/PathSensitive/CheckerVisitor.h
index f5145bbb7a67..37ec8def50b3 100644
--- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h
+++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.h
@@ -66,6 +66,11 @@ break;
default:
assert(false && "Unsupport statement.");
return;
+ case Stmt::CompoundAssignOperatorClass:
+ static_cast<ImplClass*>(this)->PostVisitBinaryOperator(C,
+ static_cast<const BinaryOperator*>(S));
+ break;
+
#define POSTVISIT(NAME, FALLBACK) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->\
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index fb0e88301fd6..df90ad9f7f08 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -270,8 +270,8 @@ protected:
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
- void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ void VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst, bool asLValue);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 70c17accb725..5606df0014f0 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -105,7 +105,8 @@ public:
// FIXME: Make out-of-line.
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
- const MemRegion *region) {
+ const MemRegion *region,
+ QualType EleTy) {
return UnknownVal();
}
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 14f735655f13..08945635e6c9 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -270,6 +270,7 @@ BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
BUILTIN(__builtin_constant_p, "Us.", "nc")
BUILTIN(__builtin_classify_type, "i.", "nc")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
+BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin_va_start, "vA.", "n")
BUILTIN(__builtin_va_end, "vA", "n")
BUILTIN(__builtin_va_copy, "vAA", "n")
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index 6315c16dd80a..0062846a7a52 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -79,12 +79,7 @@ BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
@@ -99,7 +94,6 @@ BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pmullw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "")
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index dfb6f8ddc1da..8cdf85082b16 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -83,5 +83,7 @@ def warn_drv_assuming_mfloat_abi_is : Warning<
"unknown platform, assuming -mfloat-abi=%0">;
def warn_ignoring_ftabstop_value : Warning<
"ignoring invalid -ftabstop value '%0', using default value %1">;
+def warn_drv_missing_resource_library : Warning<
+ "missing resource library '%0', link may fail">;
}
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 26a80b51c852..3f765bdfb3b7 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -172,9 +172,6 @@ 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': %1">, DefaultFatal;
-def warn_pp_relative_include_from_framework : Warning<
- "published framework headers should always #import headers within the "
- "framework with framework paths">, InGroup<DiagGroup<"framework-headers">>;
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>">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 7e59f88fcef5..8d75d2e25722 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -412,6 +412,15 @@ def err_class_redeclared_with_different_access : Error<
"%0 redeclared with '%1' access">;
def note_previous_access_declaration : Note<
"previously declared '%1' here">;
+def err_access_outside_class : Error<
+ "access to %select{private|protected}0 member outside any class context">;
+def note_access_natural : Note<"declared %select{private|protected}0 here">;
+def note_access_constrained_by_path : Note<
+ "access to decl constrained by %select{private|protected}0 inheritance">;
+def err_access_protected : Error<
+ "access to protected member of %0 from %1, which is not a subclass">;
+def err_access_private : Error<
+ "access to private member of %0 from %1">;
// C++ name lookup
def err_incomplete_nested_name_spec : Error<
@@ -537,8 +546,9 @@ def err_destructor_name : Error<
// C++ initialization
def err_init_conversion_failed : Error<
"cannot initialize %select{a variable|a parameter|return object|an "
- "exception object|a value|a base class|a member subobject|an array element}0"
- " of type %1 with an %select{rvalue|lvalue}2 of type %3">;
+ "exception object|a member subobject|an array element|a new value|a value|a "
+ "base class|an array element}0 of type %1 with an %select{rvalue|lvalue}2 of "
+ "type %3">;
def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
def err_invalid_initialization : Error<
@@ -913,10 +923,24 @@ def note_ovl_candidate_arity : Note<"candidate "
"function (the implicit copy assignment operator)}0 not viable: requires"
"%select{ at least| at most|}2 %3 argument%s3, but %4 %plural{1:was|:were}4 "
"provided">;
+
def note_ovl_candidate_deleted : Note<
"candidate %select{function|function|constructor|"
"function |function |constructor |||}0%1 "
"has been explicitly %select{made unavailable|deleted}2">;
+
+// Giving the index of the bad argument really clutters this message, and
+// it's relatively unimportant because 1) it's generally obvious which
+// argument(s) are of the given object type and 2) the fix is usually
+// to complete the type, which doesn't involve changes to the call line
+// anyway. If people complain, we can change it.
+def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)}0%1 "
+ "not viable: cannot convert argument of incomplete type %2 to %3">;
def note_ovl_candidate_bad_conv : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
@@ -1840,6 +1864,9 @@ def err_illegal_super_cast : Error<
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
"use @synthesize, @dynamic or provide a method implementation">;
+def warn_setter_getter_impl_required_in_category : Warning<
+ "property %0 requires method %1 to be defined - "
+ "use @dynamic or provide a method implementation in category">;
def note_property_impl_required : Note<
"implementation is here">;
@@ -2458,8 +2485,6 @@ def warn_stringcompare : Warning<
def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
" or pick a deployment target that supports them">;
def err_expected_block_lbrace : Error<"expected '{' in block literal">;
-def err_goto_in_block : Error<
- "goto not allowed in block literal">;
def err_return_in_block_expression : Error<
"return not allowed in block expression literal">;
def err_block_returns_array : Error<
diff --git a/include/clang/Basic/MacroBuilder.h b/include/clang/Basic/MacroBuilder.h
new file mode 100644
index 000000000000..3287b304c97f
--- /dev/null
+++ b/include/clang/Basic/MacroBuilder.h
@@ -0,0 +1,46 @@
+//===--- MacroBuilder.h - CPP Macro building utility ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the MacroBuilder utility class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_MACROBUILDER_H
+#define LLVM_CLANG_BASIC_MACROBUILDER_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+class MacroBuilder {
+ llvm::raw_ostream &Out;
+public:
+ MacroBuilder(llvm::raw_ostream &Output) : Out(Output) {}
+
+ /// Append a #define line for macro of the form "#define Name Value\n".
+ void defineMacro(const llvm::Twine &Name, const llvm::Twine &Value = "1") {
+ Out << "#define " << Name << ' ' << Value << '\n';
+ }
+
+ /// Append a #undef line for Name. Name should be of the form XXX
+ /// and we emit "#undef XXX".
+ void undefineMacro(const llvm::Twine &Name) {
+ Out << "#undef " << Name << '\n';
+ }
+
+ /// Directly append Str and a newline to the underlying buffer.
+ void append(const llvm::Twine &Str) {
+ Out << Str << '\n';
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile
index b85eb0725ef0..48f7f9d8cc7b 100644
--- a/include/clang/Basic/Makefile
+++ b/include/clang/Basic/Makefile
@@ -11,14 +11,12 @@ include $(LEVEL)/Makefile.common
INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td)
-$(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN)
+$(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang $(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) diagnostic tables with tblgen"
- $(Verb) -$(MKDIR) $(@D)
$(Verb) $(TableGen) -gen-clang-diags-defs -clang-component=$(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) -o $(call SYSPATH, $@) $<
-$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN)
+$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang diagnostic groups with tblgen"
- $(Verb) -$(MKDIR) $(@D)
$(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $<
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
new file mode 100644
index 000000000000..4cace86dd18d
--- /dev/null
+++ b/include/clang/Basic/Specifiers.h
@@ -0,0 +1,82 @@
+//===--- Specifiers.h - Declaration and Type Specifiers ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines various enumerations that describe declaration and
+// type specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H
+#define LLVM_CLANG_BASIC_SPECIFIERS_H
+
+namespace clang {
+ /// \brief Specifies the width of a type, e.g., short, long, or long long.
+ enum TypeSpecifierWidth {
+ TSW_unspecified,
+ TSW_short,
+ TSW_long,
+ TSW_longlong
+ };
+
+ /// \brief Specifies the signedness of a type, e.g., signed or unsigned.
+ enum TypeSpecifierSign {
+ TSS_unspecified,
+ TSS_signed,
+ TSS_unsigned
+ };
+
+ /// \brief Specifies the kind of type.
+ enum TypeSpecifierType {
+ TST_unspecified,
+ TST_void,
+ TST_char,
+ TST_wchar, // C++ wchar_t
+ TST_char16, // C++0x char16_t
+ TST_char32, // C++0x char32_t
+ TST_int,
+ TST_float,
+ TST_double,
+ TST_bool, // _Bool
+ TST_decimal32, // _Decimal32
+ TST_decimal64, // _Decimal64
+ TST_decimal128, // _Decimal128
+ TST_enum,
+ TST_union,
+ TST_struct,
+ TST_class, // C++ class type
+ TST_typename, // Typedef, C++ class-name or enum name, etc.
+ TST_typeofType,
+ TST_typeofExpr,
+ TST_decltype, // C++0x decltype
+ TST_auto, // C++0x auto
+ TST_error // erroneous type
+ };
+
+ /// WrittenBuiltinSpecs - Structure that packs information about the
+ /// type specifiers that were written in a particular type specifier
+ /// sequence.
+ struct WrittenBuiltinSpecs {
+ /*DeclSpec::TST*/ unsigned Type : 5;
+ /*DeclSpec::TSS*/ unsigned Sign : 2;
+ /*DeclSpec::TSW*/ unsigned Width : 2;
+ bool ModeAttr : 1;
+ };
+
+ /// AccessSpecifier - A C++ access specifier (public, private,
+ /// protected), plus the special value "none" which means
+ /// different things in different contexts.
+ enum AccessSpecifier {
+ AS_public,
+ AS_protected,
+ AS_private,
+ AS_none
+ };
+}
+
+#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
index 120d5a4210d0..4710b6b608e6 100644
--- a/include/clang/Basic/Version.h
+++ b/include/clang/Basic/Version.h
@@ -15,6 +15,8 @@
#ifndef LLVM_CLANG_BASIC_VERSION_H
#define LLVM_CLANG_BASIC_VERSION_H
+#include "llvm/ADT/StringRef.h"
+
/// \brief Clang major version
#define CLANG_VERSION_MAJOR 1
@@ -47,13 +49,23 @@
#endif
namespace clang {
- /// \brief Retrieves the Subversion path that identifies the particular
- /// Clang branch, tag, or trunk from which this Clang was built.
- const char *getClangSubversionPath();
+ /// \brief Retrieves the repository path (e.g., Subversion path) that
+ /// identifies the particular Clang branch, tag, or trunk from which this
+ /// Clang was built.
+ llvm::StringRef getClangRepositoryPath();
+
+ /// \brief Retrieves the repository revision number (or identifer) from which
+ /// this Clang was built.
+ llvm::StringRef getClangRevision();
+
+ /// \brief Retrieves the full repository version that is an amalgamation of
+ /// the information in getClangRepositoryPath() and getClangRevision().
+ llvm::StringRef getClangFullRepositoryVersion();
- /// \brief Retrieves the Subversion revision number from which this Clang
- /// was built.
- unsigned getClangSubversionRevision();
+ /// \brief Retrieves a string representing the complete clang version,
+ /// which includes the clang version number, the repository version,
+ /// and the vendor tag.
+ const char *getClangFullVersion();
}
#endif // LLVM_CLANG_BASIC_VERSION_H
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 8933619b2c25..3186471ce613 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -61,6 +61,9 @@ public:
/// command line.
std::string Dir;
+ /// The path to the compiler resource directory.
+ std::string ResourceDir;
+
/// Default host triple.
std::string DefaultHostTriple;
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index f18972ab3445..2659dbb2a30c 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -21,6 +21,11 @@
#include <string>
#include <vector>
#include <cassert>
+#include <utility>
+
+namespace llvm {
+ class MemoryBuffer;
+}
namespace clang {
class ASTContext;
@@ -111,6 +116,10 @@ public:
return TopLevelDecls;
}
+ /// \brief A mapping from a file name to the memory buffer that stores the
+ /// remapped contents of that file.
+ typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
+
/// \brief Create a ASTUnit from a PCH file.
///
/// \param Filename - The PCH file to load.
@@ -122,7 +131,9 @@ public:
static ASTUnit *LoadFromPCHFile(const std::string &Filename,
Diagnostic &Diags,
bool OnlyLocalDecls = false,
- bool UseBumpAllocator = false);
+ bool UseBumpAllocator = false,
+ RemappedFile *RemappedFiles = 0,
+ unsigned NumRemappedFiles = 0);
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
/// CompilerInvocation object.
@@ -158,7 +169,9 @@ public:
Diagnostic &Diags,
llvm::StringRef ResourceFilesPath,
bool OnlyLocalDecls = false,
- bool UseBumpAllocator = false);
+ bool UseBumpAllocator = false,
+ RemappedFile *RemappedFiles = 0,
+ unsigned NumRemappedFiles = 0);
};
} // namespace clang
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index 536bd4139006..1a9f4ceab933 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -30,7 +30,7 @@ namespace clang {
/// designed for the previous version could not support reading
/// the new version), this number should be increased.
///
- /// Version 3 of PCH files also requires that the Subversion branch and
+ /// Version 3 of PCH files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// PCH files at this time.
const unsigned VERSION_MAJOR = 3;
@@ -219,9 +219,9 @@ namespace clang {
/// comments were encountered in the source code.
COMMENT_RANGES = 20,
- /// \brief Record code for the Subversion branch and revision information
- /// of the compiler used to build this PCH file.
- SVN_BRANCH_REVISION = 21
+ /// \brief Record code for the version control branch and revision
+ /// information of the compiler used to build this PCH file.
+ VERSION_CONTROL_BRANCH_REVISION = 21
};
/// \brief Record types used within a source manager block.
@@ -676,7 +676,17 @@ namespace clang {
/// \brief A CXXOperatorCallExpr record.
EXPR_CXX_OPERATOR_CALL,
/// \brief A CXXConstructExpr record.
- EXPR_CXX_CONSTRUCT
+ EXPR_CXX_CONSTRUCT,
+ // \brief A CXXStaticCastExpr record.
+ EXPR_CXX_STATIC_CAST,
+ // \brief A CXXDynamicCastExpr record.
+ EXPR_CXX_DYNAMIC_CAST,
+ // \brief A CXXReinterpretCastExpr record.
+ EXPR_CXX_REINTERPRET_CAST,
+ // \brief A CXXConstCastExpr record.
+ EXPR_CXX_CONST_CAST,
+ // \brief A CXXFunctionalCastExpr record.
+ EXPR_CXX_FUNCTIONAL_CAST
};
/// \brief The kinds of designators that can occur in a
diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h
index c43a1feb8c05..7ba7c5c38dab 100644
--- a/include/clang/Frontend/PreprocessorOptions.h
+++ b/include/clang/Frontend/PreprocessorOptions.h
@@ -16,6 +16,10 @@
#include <utility>
#include <vector>
+namespace llvm {
+ class MemoryBuffer;
+}
+
namespace clang {
class Preprocessor;
@@ -48,6 +52,12 @@ public:
/// pair).
std::vector<std::pair<std::string, std::string> > RemappedFiles;
+ /// \brief The set of file-to-buffer remappings, which take existing files
+ /// on the system (the first part of each pair) and gives them the contents
+ /// of the specified memory buffer (the second part of each pair).
+ std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >
+ RemappedFileBuffers;
+
typedef std::vector<std::pair<std::string, std::string> >::const_iterator
remapped_file_iterator;
remapped_file_iterator remapped_file_begin() const {
@@ -57,6 +67,15 @@ public:
return RemappedFiles.end();
}
+ typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
+ const_iterator remapped_file_buffer_iterator;
+ remapped_file_buffer_iterator remapped_file_buffer_begin() const {
+ return RemappedFileBuffers.begin();
+ }
+ remapped_file_buffer_iterator remapped_file_buffer_end() const {
+ return RemappedFileBuffers.end();
+ }
+
public:
PreprocessorOptions() : UsePredefines(true) {}
@@ -69,6 +88,9 @@ public:
void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
RemappedFiles.push_back(std::make_pair(From, To));
}
+ void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) {
+ RemappedFileBuffers.push_back(std::make_pair(From, To));
+ }
};
} // end namespace clang
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index c8df4941cc21..7f43b2ad80ff 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -15,7 +15,6 @@
#define LLVM_CLANG_FRONTEND_UTILS_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
@@ -41,28 +40,6 @@ class Stmt;
class TargetInfo;
class FrontendOptions;
-class MacroBuilder {
- llvm::raw_ostream &Out;
-public:
- MacroBuilder(llvm::raw_ostream &Output) : Out(Output) {}
-
- /// Append a #define line for macro of the form "#define Name Value\n".
- void defineMacro(const llvm::Twine &Name, const llvm::Twine &Value = "1") {
- Out << "#define " << Name << ' ' << Value << '\n';
- }
-
- /// Append a #undef line for Name. Name should be of the form XXX
- /// and we emit "#undef XXX".
- void undefineMacro(const llvm::Twine &Name) {
- Out << "#undef " << Name << '\n';
- }
-
- /// Directly append Str and a newline to the underlying buffer.
- void append(const llvm::Twine &Str) {
- Out << Str << '\n';
- }
-};
-
/// Normalize \arg File for use in a user defined #include directive (in the
/// predefines buffer).
std::string NormalizeDashIncludePath(llvm::StringRef File);
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index fc2671f48112..dedbbd868a99 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -602,7 +602,12 @@ public:
/// the returned source location would not be meaningful (e.g., if
/// it points into a macro), this routine returns an invalid
/// source location.
- SourceLocation getLocForEndOfToken(SourceLocation Loc);
+ ///
+ /// \param Offset an offset from the end of the token, where the source
+ /// location should refer to. The default offset (0) produces a source
+ /// location pointing just past the end of the token; an offset of 1 produces
+ /// a source location pointing to the last character in the token, etc.
+ SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
/// DumpToken - Print the token to stderr, used for debugging.
///
@@ -697,8 +702,7 @@ public:
/// return null on failure. isAngled indicates whether the file reference is
/// for system #include's or not (i.e. using <> instead of "").
const FileEntry *LookupFile(llvm::StringRef Filename,
- SourceLocation FilenameTokLoc, bool isAngled,
- const DirectoryLookup *FromDir,
+ bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir);
/// GetCurLookup - The DirectoryLookup structure used to find the current
@@ -884,7 +888,9 @@ public:
void HandlePragmaSystemHeader(Token &SysHeaderTok);
void HandlePragmaDependency(Token &DependencyTok);
void HandlePragmaComment(Token &CommentTok);
- void HandleComment(SourceRange Comment);
+ // Return true and store the first token only if any CommentHandler
+ // has inserted some tokens and getCommentRetentionState() is false.
+ bool HandleComment(Token &Token, SourceRange Comment);
};
/// \brief Abstract base class that describes a handler that will receive
@@ -893,7 +899,9 @@ class CommentHandler {
public:
virtual ~CommentHandler();
- virtual void HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
+ // The handler shall return true if it has pushed any tokens
+ // to be read using e.g. EnterToken or EnterTokenStream.
+ virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
};
} // end namespace clang
diff --git a/include/clang/Parse/AccessSpecifier.h b/include/clang/Parse/AccessSpecifier.h
deleted file mode 100644
index 8d2cee8ea43a..000000000000
--- a/include/clang/Parse/AccessSpecifier.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===--- AccessSpecifier.h - C++ Access Specifiers -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines interfaces used for C++ access specifiers.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H
-#define LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H
-
-namespace clang {
-
-/// AccessSpecifier - A C++ access specifier (none, public, private,
-/// protected).
-enum AccessSpecifier {
- AS_none,
- AS_public,
- AS_protected,
- AS_private
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 7209e0a843cd..ff33f5039d5d 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -16,9 +16,9 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TypeTraits.h"
-#include "clang/Parse/AccessSpecifier.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Ownership.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -2110,6 +2110,7 @@ public:
SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
return DeclPtrTy();
@@ -2131,6 +2132,7 @@ public:
SourceLocation ProtocolLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
return DeclPtrTy();
@@ -2144,6 +2146,7 @@ public:
SourceLocation CategoryLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc) {
return DeclPtrTy();
}
@@ -2771,6 +2774,7 @@ public:
SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
};
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 6a3d8a924e07..f923b5e910db 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -17,6 +17,7 @@
#include "clang/Parse/AttributeList.h"
#include "clang/Lex/Token.h"
#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
@@ -78,51 +79,50 @@ public:
SCS_mutable
};
- // type-specifier
- enum TSW {
- TSW_unspecified,
- TSW_short,
- TSW_long,
- TSW_longlong
- };
-
+ // Import type specifier width enumeration and constants.
+ typedef TypeSpecifierWidth TSW;
+ static const TSW TSW_unspecified = clang::TSW_unspecified;
+ static const TSW TSW_short = clang::TSW_short;
+ static const TSW TSW_long = clang::TSW_long;
+ static const TSW TSW_longlong = clang::TSW_longlong;
+
enum TSC {
TSC_unspecified,
TSC_imaginary,
TSC_complex
};
- enum TSS {
- TSS_unspecified,
- TSS_signed,
- TSS_unsigned
- };
-
- enum TST {
- TST_unspecified,
- TST_void,
- TST_char,
- TST_wchar, // C++ wchar_t
- TST_char16, // C++0x char16_t
- TST_char32, // C++0x char32_t
- TST_int,
- TST_float,
- TST_double,
- TST_bool, // _Bool
- TST_decimal32, // _Decimal32
- TST_decimal64, // _Decimal64
- TST_decimal128, // _Decimal128
- TST_enum,
- TST_union,
- TST_struct,
- TST_class, // C++ class type
- TST_typename, // Typedef, C++ class-name or enum name, etc.
- TST_typeofType,
- TST_typeofExpr,
- TST_decltype, // C++0x decltype
- TST_auto, // C++0x auto
- TST_error // erroneous type
- };
+ // Import type specifier sign enumeration and constants.
+ typedef TypeSpecifierSign TSS;
+ static const TSS TSS_unspecified = clang::TSS_unspecified;
+ static const TSS TSS_signed = clang::TSS_signed;
+ static const TSS TSS_unsigned = clang::TSS_unsigned;
+
+ // Import type specifier type enumeration and constants.
+ typedef TypeSpecifierType TST;
+ static const TST TST_unspecified = clang::TST_unspecified;
+ static const TST TST_void = clang::TST_void;
+ static const TST TST_char = clang::TST_char;
+ static const TST TST_wchar = clang::TST_wchar;
+ static const TST TST_char16 = clang::TST_char16;
+ static const TST TST_char32 = clang::TST_char32;
+ static const TST TST_int = clang::TST_int;
+ static const TST TST_float = clang::TST_float;
+ static const TST TST_double = clang::TST_double;
+ static const TST TST_bool = clang::TST_bool;
+ static const TST TST_decimal32 = clang::TST_decimal32;
+ static const TST TST_decimal64 = clang::TST_decimal64;
+ static const TST TST_decimal128 = clang::TST_decimal128;
+ static const TST TST_enum = clang::TST_enum;
+ static const TST TST_union = clang::TST_union;
+ static const TST TST_struct = clang::TST_struct;
+ static const TST TST_class = clang::TST_class;
+ static const TST TST_typename = clang::TST_typename;
+ static const TST TST_typeofType = clang::TST_typeofType;
+ static const TST TST_typeofExpr = clang::TST_typeofExpr;
+ static const TST TST_decltype = clang::TST_decltype;
+ static const TST TST_auto = clang::TST_auto;
+ static const TST TST_error = clang::TST_error;
// type-qualifiers
enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ.
@@ -199,6 +199,9 @@ private:
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
SourceLocation FriendLoc, ConstexprLoc;
+ WrittenBuiltinSpecs writtenBS;
+ void SaveWrittenBuiltinSpecs();
+
DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
void operator=(const DeclSpec&); // DO NOT IMPLEMENT
public:
@@ -411,6 +414,10 @@ public:
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
void Finish(Diagnostic &D, Preprocessor &PP);
+ const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
+ return writtenBS;
+ }
+
/// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
/// without a Declarator. Only tag declspecs can stand alone.
bool isMissingDeclaratorOk();
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 0fc9413c30c3..e7cb0a2493d3 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_PARSE_PARSER_H
#define LLVM_CLANG_PARSE_PARSER_H
+#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/AccessSpecifier.h"
#include "clang/Parse/Action.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/ADT/OwningPtr.h"
diff --git a/include/clang/Rewrite/DeltaTree.h b/include/clang/Rewrite/DeltaTree.h
index 7e0796524c6d..f32906a323e0 100644
--- a/include/clang/Rewrite/DeltaTree.h
+++ b/include/clang/Rewrite/DeltaTree.h
@@ -17,7 +17,7 @@
namespace clang {
/// DeltaTree - a multiway search tree (BTree) structure with some fancy
- /// features. B-Trees are are generally more memory and cache efficient than
+ /// features. B-Trees are generally more memory and cache efficient than
/// binary trees, because they store multiple keys/values in each node. This
/// implements a key/value mapping from index to delta, and allows fast lookup
/// on index. However, an added (important) bonus is that it can also
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 76ec852cb89e..c1bc70989d4e 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1200,43 +1200,58 @@ QualType ASTContext::getObjCGCQualType(QualType T,
return getExtQualType(TypeNode, Quals);
}
-QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
+static QualType getNoReturnCallConvType(ASTContext& Context, QualType T,
+ bool AddNoReturn,
+ CallingConv CallConv) {
QualType ResultType;
if (const PointerType *Pointer = T->getAs<PointerType>()) {
QualType Pointee = Pointer->getPointeeType();
- ResultType = getNoReturnType(Pointee, AddNoReturn);
+ ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
+ CallConv);
if (ResultType == Pointee)
return T;
-
- ResultType = getPointerType(ResultType);
+
+ ResultType = Context.getPointerType(ResultType);
} else if (const BlockPointerType *BlockPointer
= T->getAs<BlockPointerType>()) {
QualType Pointee = BlockPointer->getPointeeType();
- ResultType = getNoReturnType(Pointee, AddNoReturn);
+ ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
+ CallConv);
if (ResultType == Pointee)
return T;
-
- ResultType = getBlockPointerType(ResultType);
- } else if (const FunctionType *F = T->getAs<FunctionType>()) {
- if (F->getNoReturnAttr() == AddNoReturn)
+
+ ResultType = Context.getBlockPointerType(ResultType);
+ } else if (const FunctionType *F = T->getAs<FunctionType>()) {
+ if (F->getNoReturnAttr() == AddNoReturn && F->getCallConv() == CallConv)
return T;
-
+
if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
- ResultType = getFunctionNoProtoType(FNPT->getResultType(), AddNoReturn);
+ ResultType = Context.getFunctionNoProtoType(FNPT->getResultType(),
+ AddNoReturn, CallConv);
} else {
const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
ResultType
- = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
- FPT->getNumArgs(), FPT->isVariadic(),
- FPT->getTypeQuals(),
- FPT->hasExceptionSpec(), FPT->hasAnyExceptionSpec(),
- FPT->getNumExceptions(), FPT->exception_begin(),
- AddNoReturn);
+ = Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
+ FPT->getNumArgs(), FPT->isVariadic(),
+ FPT->getTypeQuals(),
+ FPT->hasExceptionSpec(),
+ FPT->hasAnyExceptionSpec(),
+ FPT->getNumExceptions(),
+ FPT->exception_begin(),
+ AddNoReturn, CallConv);
}
} else
return T;
-
- return getQualifiedType(ResultType, T.getLocalQualifiers());
+
+ return Context.getQualifiedType(ResultType, T.getLocalQualifiers());
+}
+
+QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
+ return getNoReturnCallConvType(*this, T, AddNoReturn, T.getCallConv());
+}
+
+QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) {
+ return getNoReturnCallConvType(*this, T, T.getNoReturnAttr(), CallConv);
}
/// getComplexType - Return the uniqued reference to the type for a complex
@@ -1679,9 +1694,16 @@ QualType ASTContext::getDependentSizedExtVectorType(QualType vecType,
return QualType(New, 0);
}
+static CallingConv getCanonicalCallingConv(CallingConv CC) {
+ if (CC == CC_C)
+ return CC_Default;
+ return CC;
+}
+
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
-QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
+QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
+ CallingConv CallConv) {
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
@@ -1693,8 +1715,10 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
return QualType(FT, 0);
QualType Canonical;
- if (!ResultTy.isCanonical()) {
- Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);
+ if (!ResultTy.isCanonical() ||
+ getCanonicalCallingConv(CallConv) != CallConv) {
+ Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn,
+ getCanonicalCallingConv(CallConv));
// Get the new insert position for the node we care about.
FunctionNoProtoType *NewIP =
@@ -1715,7 +1739,8 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals, bool hasExceptionSpec,
bool hasAnyExceptionSpec, unsigned NumExs,
- const QualType *ExArray, bool NoReturn) {
+ const QualType *ExArray, bool NoReturn,
+ CallingConv CallConv) {
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
@@ -1737,7 +1762,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
// If this type isn't canonical, get the canonical version of it.
// The exception spec is not part of the canonical type.
QualType Canonical;
- if (!isCanonical) {
+ if (!isCanonical || getCanonicalCallingConv(CallConv) != CallConv) {
llvm::SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
@@ -1746,7 +1771,8 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
Canonical = getFunctionType(getCanonicalType(ResultTy),
CanonicalArgs.data(), NumArgs,
isVariadic, TypeQuals, false,
- false, 0, 0, NoReturn);
+ false, 0, 0, NoReturn,
+ getCanonicalCallingConv(CallConv));
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@@ -1763,7 +1789,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
NumExs*sizeof(QualType), TypeAlignment);
new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
- ExArray, NumExs, Canonical, NoReturn);
+ ExArray, NumExs, Canonical, NoReturn, CallConv);
Types.push_back(FTP);
FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
@@ -2101,7 +2127,8 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
// No Match;
ObjCObjectPointerType *QType = new (*this, TypeAlignment)
- ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols);
+ ObjCObjectPointerType(*this, Canonical, InterfaceT, Protocols,
+ NumProtocols);
Types.push_back(QType);
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
@@ -2135,7 +2162,7 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
}
ObjCInterfaceType *QType = new (*this, TypeAlignment)
- ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
+ ObjCInterfaceType(*this, Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
Protocols, NumProtocols);
Types.push_back(QType);
@@ -3733,8 +3760,8 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
/// \brief Retrieve the template name that corresponds to a non-empty
/// lookup.
-TemplateName ASTContext::getOverloadedTemplateName(NamedDecl * const *Begin,
- NamedDecl * const *End) {
+TemplateName ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
unsigned size = End - Begin;
assert(size > 1 && "set is not overloaded!");
@@ -3743,7 +3770,7 @@ TemplateName ASTContext::getOverloadedTemplateName(NamedDecl * const *Begin,
OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size);
NamedDecl **Storage = OT->getStorage();
- for (NamedDecl * const *I = Begin; I != End; ++I) {
+ for (UnresolvedSetIterator I = Begin; I != End; ++I) {
NamedDecl *D = *I;
assert(isa<FunctionTemplateDecl>(D) ||
(isa<UsingShadowDecl>(D) &&
@@ -4211,6 +4238,10 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS) {
return !mergeTypes(LHS, RHS).isNull();
}
+static bool isSameCallingConvention(CallingConv lcc, CallingConv rcc) {
+ return (getCanonicalCallingConv(lcc) == getCanonicalCallingConv(rcc));
+}
+
QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
const FunctionType *lbase = lhs->getAs<FunctionType>();
const FunctionType *rbase = rhs->getAs<FunctionType>();
@@ -4232,6 +4263,11 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
allLTypes = false;
if (NoReturn != rbase->getNoReturnAttr())
allRTypes = false;
+ CallingConv lcc = lbase->getCallConv();
+ CallingConv rcc = rbase->getCallConv();
+ // Compatible functions must have compatible calling conventions
+ if (!isSameCallingConvention(lcc, rcc))
+ return QualType();
if (lproto && rproto) { // two C99 style function prototypes
assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
@@ -4267,7 +4303,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
if (allRTypes) return rhs;
return getFunctionType(retType, types.begin(), types.size(),
lproto->isVariadic(), lproto->getTypeQuals(),
- NoReturn);
+ NoReturn, lcc);
}
if (lproto) allRTypes = false;
@@ -4294,12 +4330,12 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
if (allRTypes) return rhs;
return getFunctionType(retType, proto->arg_type_begin(),
proto->getNumArgs(), proto->isVariadic(),
- proto->getTypeQuals(), NoReturn);
+ proto->getTypeQuals(), NoReturn, lcc);
}
if (allLTypes) return lhs;
if (allRTypes) return rhs;
- return getFunctionNoProtoType(retType, NoReturn);
+ return getFunctionNoProtoType(retType, NoReturn, lcc);
}
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 92a58b76d878..720832869266 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -145,7 +145,11 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
void *UserData,
CXXBasePaths &Paths) const {
bool FoundPath = false;
-
+
+ // The access of the path down to this record.
+ AccessSpecifier AccessToHere = Paths.ScratchPath.Access;
+ bool IsFirstStep = Paths.ScratchPath.empty();
+
ASTContext &Context = getASTContext();
for (base_class_const_iterator BaseSpec = bases_begin(),
BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) {
@@ -189,10 +193,31 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
else
Element.SubobjectNumber = Subobjects.second;
Paths.ScratchPath.push_back(Element);
+
+ // Calculate the "top-down" access to this base class.
+ // The spec actually describes this bottom-up, but top-down is
+ // equivalent because the definition works out as follows:
+ // 1. Write down the access along each step in the inheritance
+ // chain, followed by the access of the decl itself.
+ // For example, in
+ // class A { public: int foo; };
+ // class B : protected A {};
+ // class C : public B {};
+ // class D : private C {};
+ // we would write:
+ // private public protected public
+ // 2. If 'private' appears anywhere except far-left, access is denied.
+ // 3. Otherwise, overall access is determined by the most restrictive
+ // access in the sequence.
+ if (IsFirstStep)
+ Paths.ScratchPath.Access = BaseSpec->getAccessSpecifier();
+ else
+ Paths.ScratchPath.Access
+ = MergeAccess(AccessToHere, BaseSpec->getAccessSpecifier());
}
if (BaseMatches(BaseSpec, Paths.ScratchPath, UserData)) {
- // We've found a path that terminates that this base.
+ // We've found a path that terminates at this base.
FoundPath = true;
if (Paths.isRecordingPaths()) {
// We have a path. Make a copy of it before moving on.
@@ -223,13 +248,18 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
// Pop this base specifier off the current path (if we're
// collecting paths).
- if (Paths.isRecordingPaths())
+ if (Paths.isRecordingPaths()) {
Paths.ScratchPath.pop_back();
+ }
+
// If we set a virtual earlier, and this isn't a path, forget it again.
if (SetVirtual && !FoundPath) {
Paths.DetectedVirtual = 0;
}
}
+
+ // Reset the scratch path access.
+ Paths.ScratchPath.Access = AccessToHere;
return FoundPath;
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e77661a9fbd4..794b14a1f4a1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -629,9 +629,13 @@ VarDecl::~VarDecl() {
}
SourceRange VarDecl::getSourceRange() const {
+ SourceLocation Start = getTypeSpecStartLoc();
+ if (Start.isInvalid())
+ Start = getLocation();
+
if (getInit())
- return SourceRange(getLocation(), getInit()->getLocEnd());
- return SourceRange(getLocation(), getLocation());
+ return SourceRange(Start, getInit()->getLocEnd());
+ return SourceRange(Start, getLocation());
}
bool VarDecl::isOutOfLine() const {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 3afb4e44f3eb..84aa81ca76db 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -102,6 +102,17 @@ bool Decl::isFunctionOrFunctionTemplate() const {
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
}
+bool Decl::isDefinedOutsideFunctionOrMethod() const {
+ for (const DeclContext *DC = getDeclContext();
+ DC && !DC->isTranslationUnit();
+ DC = DC->getParent())
+ if (DC->isFunctionOrMethod())
+ return false;
+
+ return true;
+}
+
+
//===----------------------------------------------------------------------===//
// PrettyStackTraceDecl Implementation
//===----------------------------------------------------------------------===//
@@ -399,8 +410,13 @@ SourceLocation Decl::getBodyRBrace() const {
#ifndef NDEBUG
void Decl::CheckAccessDeclContext() const {
- // If the decl is the toplevel translation unit or if we're not in a
- // record decl context, we don't need to check anything.
+ // Suppress this check if any of the following hold:
+ // 1. this is the translation unit (and thus has no parent)
+ // 2. this is a template parameter (and thus doesn't belong to its context)
+ // 3. this is a ParmVarDecl (which can be in a record context during
+ // the brief period between its creation and the creation of the
+ // FunctionDecl)
+ // 4. the context is not a record
if (isa<TranslationUnitDecl>(this) ||
!isa<CXXRecordDecl>(getDeclContext()))
return;
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 1cce35c0b39a..fe6064df325a 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -312,8 +312,9 @@ void
CXXRecordDecl::collectConversionFunctions(
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const
{
- const UnresolvedSet *Cs = getConversionFunctions();
- for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
+ const UnresolvedSetImpl *Cs = getConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Cs->begin(), E = Cs->end();
+ I != E; ++I) {
NamedDecl *TopConv = *I;
CanQualType TConvType;
if (FunctionTemplateDecl *TConversionTemplate =
@@ -344,10 +345,11 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
bool inTopClass = (RD == this);
QualType ClassType = getASTContext().getTypeDeclType(this);
if (const RecordType *Record = ClassType->getAs<RecordType>()) {
- const UnresolvedSet *Cs
+ const UnresolvedSetImpl *Cs
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
- for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
+ for (UnresolvedSetImpl::iterator I = Cs->begin(), E = Cs->end();
+ I != E; ++I) {
NamedDecl *Conv = *I;
// Only those conversions not exact match of conversions in current
// class are candidateconversion routines.
@@ -410,7 +412,7 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
-const UnresolvedSet *CXXRecordDecl::getVisibleConversionFunctions() {
+const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
// If root class, all conversions are visible.
if (bases_begin() == bases_end())
return &Conversions;
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 2506f27e6f8c..ffda505aaab1 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -37,6 +37,21 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
memcpy(List, InList, sizeof(void*)*Elts);
}
+void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
+ const SourceLocation *Locs, ASTContext &Ctx) {
+ if (Elts == 0)
+ return;
+
+ Locations = new (Ctx) SourceLocation[Elts];
+ memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
+ set(InList, Elts, Ctx);
+}
+
+void ObjCProtocolList::Destroy(ASTContext &Ctx) {
+ Ctx.Deallocate(Locations);
+ Locations = 0;
+ ObjCList<ObjCProtocolDecl>::Destroy(Ctx);
+}
//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
@@ -141,16 +156,18 @@ ObjCContainerDecl::FindPropertyVisibleInPrimaryClass(
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
+ const SourceLocation *Locs,
ASTContext &C)
{
if (ReferencedProtocols.empty()) {
- ReferencedProtocols.set(ExtList, ExtNum, C);
+ ReferencedProtocols.set(ExtList, ExtNum, Locs, C);
return;
}
// Check for duplicate protocol in class's protocol list.
// This is (O)2. But it is extremely rare and number of protocols in
// class or its extension are very few.
llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
@@ -164,18 +181,23 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
}
// Do we want to warn on a protocol in extension class which
// already exist in the class? Probably not.
- if (!protocolExists)
+ if (!protocolExists) {
ProtocolRefs.push_back(ProtoInExtension);
+ ProtocolLocs.push_back(Locs[i]);
+ }
}
if (ProtocolRefs.empty())
return;
// Merge ProtocolRefs into class's protocol list;
+ protocol_loc_iterator pl = protocol_loc_begin();
for (protocol_iterator p = protocol_begin(), e = protocol_end();
- p != e; p++)
+ p != e; ++p, ++pl) {
ProtocolRefs.push_back(*p);
+ ProtocolLocs.push_back(*pl);
+ }
ReferencedProtocols.Destroy(C);
unsigned NumProtoRefs = ProtocolRefs.size();
- setProtocolList((ObjCProtocolDecl**)&ProtocolRefs[0], NumProtoRefs, C);
+ setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
}
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
@@ -627,9 +649,9 @@ SourceRange ObjCClassDecl::getSourceRange() const {
ObjCForwardProtocolDecl::
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts,
- ASTContext &C)
+ const SourceLocation *Locs, ASTContext &C)
: Decl(ObjCForwardProtocol, DC, L) {
- ReferencedProtocols.set(Elts, nElts, C);
+ ReferencedProtocols.set(Elts, nElts, Locs, C);
}
@@ -637,8 +659,9 @@ ObjCForwardProtocolDecl *
ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ObjCProtocolDecl *const *Elts,
- unsigned NumElts) {
- return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, C);
+ unsigned NumElts,
+ const SourceLocation *Locs) {
+ return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C);
}
void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
@@ -651,9 +674,11 @@ void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
//===----------------------------------------------------------------------===//
ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+ SourceLocation AtLoc,
+ SourceLocation ClassNameLoc,
+ SourceLocation CategoryNameLoc,
IdentifierInfo *Id) {
- return new (C) ObjCCategoryDecl(DC, L, Id);
+ return new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id);
}
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
@@ -765,9 +790,10 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id,
+ SourceLocation AtLoc,
QualType T,
PropertyControl propControl) {
- return new (C) ObjCPropertyDecl(DC, L, Id, T);
+ return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T);
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 4c3046bed10b..fa44b510e99a 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -98,10 +98,12 @@ void DeclRefExpr::computeDependence() {
// initialized with an expression that is value-dependent.
else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (Var->getType()->isIntegralType() &&
- Var->getType().getCVRQualifiers() == Qualifiers::Const &&
- Var->getInit() &&
- Var->getInit()->isValueDependent())
- ValueDependent = true;
+ Var->getType().getCVRQualifiers() == Qualifiers::Const) {
+ const VarDecl *Def = 0;
+ if (const Expr *Init = Var->getDefinition(Def))
+ if (Init->isValueDependent())
+ ValueDependent = true;
+ }
}
// (TD) - a nested-name-specifier or a qualified-id that names a
// member of an unknown specialization.
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 81584b700270..a6574efda8ee 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -135,10 +135,11 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
return ULE;
}
-bool UnresolvedLookupExpr::ComputeDependence(NamedDecl * const *Begin,
- NamedDecl * const *End,
- const TemplateArgumentListInfo *Args) {
- for (NamedDecl * const *I = Begin; I != End; ++I)
+bool UnresolvedLookupExpr::
+ ComputeDependence(UnresolvedSetImpl::const_iterator Begin,
+ UnresolvedSetImpl::const_iterator End,
+ const TemplateArgumentListInfo *Args) {
+ for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I)
if ((*I)->getDeclContext()->isDependentContext())
return true;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index dfff2099cbd6..086249c811f9 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -506,7 +506,9 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
if (E->isBuiltinCall(Info.Ctx) ==
- Builtin::BI__builtin___CFStringMakeConstantString)
+ Builtin::BI__builtin___CFStringMakeConstantString ||
+ E->isBuiltinCall(Info.Ctx) ==
+ Builtin::BI__builtin___NSStringMakeConstantString)
return APValue(E);
return APValue();
}
@@ -971,6 +973,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_object_size: {
const Expr *Arg = E->getArg(0)->IgnoreParens();
Expr::EvalResult Base;
+
+ // TODO: Perhaps we should let LLVM lower this?
if (Arg->EvaluateAsAny(Base, Info.Ctx)
&& Base.Val.getKind() == APValue::LValue
&& !Base.HasSideEffects)
@@ -992,7 +996,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
}
- // TODO: Perhaps we should let LLVM lower this?
+ // If evaluating the argument has side-effects we can't determine
+ // the size of the object and lower it to unknown now.
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1)
return Success(-1ULL, E);
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index cfd89eaed350..0aa01801959c 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -119,6 +119,11 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
return;
}
}
+ if (i->isVirtual()) {
+ SelectPrimaryVBase(Base, FirstPrimary);
+ if (PrimaryBase.getBase())
+ return;
+ }
}
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index e0055f187825..edfb580cc35f 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -339,6 +339,25 @@ const RecordType *Type::getAsUnionType() const {
return 0;
}
+ObjCInterfaceType::ObjCInterfaceType(ASTContext &Ctx, QualType Canonical,
+ ObjCInterfaceDecl *D,
+ ObjCProtocolDecl **Protos, unsigned NumP) :
+ Type(ObjCInterface, Canonical, /*Dependent=*/false),
+ Decl(D), Protocols(0), NumProtocols(NumP)
+{
+ if (NumProtocols) {
+ Protocols = new (Ctx) ObjCProtocolDecl*[NumProtocols];
+ memcpy(Protocols, Protos, NumProtocols * sizeof(*Protocols));
+ }
+}
+
+void ObjCInterfaceType::Destroy(ASTContext& C) {
+ if (Protocols)
+ C.Deallocate(Protocols);
+ this->~ObjCInterfaceType();
+ C.Deallocate(this);
+}
+
const ObjCInterfaceType *Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCInterfaceType's, just return the canonical
// type pointer if it is the right class. There is no typedef information to
@@ -353,6 +372,26 @@ bool Type::isObjCQualifiedInterfaceType() const {
return getAsObjCQualifiedInterfaceType() != 0;
}
+ObjCObjectPointerType::ObjCObjectPointerType(ASTContext &Ctx,
+ QualType Canonical, QualType T,
+ ObjCProtocolDecl **Protos,
+ unsigned NumP) :
+ Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
+ PointeeType(T), Protocols(NULL), NumProtocols(NumP)
+{
+ if (NumProtocols) {
+ Protocols = new (Ctx) ObjCProtocolDecl*[NumProtocols];
+ memcpy(Protocols, Protos, NumProtocols * sizeof(*Protocols));
+ }
+}
+
+void ObjCObjectPointerType::Destroy(ASTContext& C) {
+ if (Protocols)
+ C.Deallocate(Protocols);
+ this->~ObjCObjectPointerType();
+ C.Deallocate(this);
+}
+
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 0840c52b4c20..fd9fbc191868 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -14,6 +14,7 @@
#include "llvm/Support/raw_ostream.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/Expr.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -135,3 +136,56 @@ SourceRange TypeOfExprTypeLoc::getSourceRange() const {
return SourceRange(getTypeofLoc(),
getUnderlyingExpr()->getSourceRange().getEnd());
}
+
+
+TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
+ else {
+ switch (getTypePtr()->getKind()) {
+ case BuiltinType::Void:
+ return TST_void;
+ case BuiltinType::Bool:
+ return TST_bool;
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ return TST_char;
+ case BuiltinType::Char16:
+ return TST_char16;
+ case BuiltinType::Char32:
+ return TST_char32;
+ case BuiltinType::WChar:
+ return TST_wchar;
+ case BuiltinType::UndeducedAuto:
+ return TST_auto;
+
+ case BuiltinType::UChar:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::UInt128:
+ case BuiltinType::SChar:
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ case BuiltinType::LongLong:
+ case BuiltinType::Int128:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ llvm_unreachable("Builtin type needs extra local data!");
+ // Fall through, if the impossible happens.
+
+ case BuiltinType::NullPtr:
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return TST_unspecified;
+ }
+ }
+
+ return TST_unspecified;
+}
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 2093b5e23e85..ad9f6dd19413 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -55,7 +55,7 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
CFG *AnalysisContext::getCFG() {
if (!cfg)
- cfg = CFG::buildCFG(getBody(), &D->getASTContext());
+ cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), AddEHEdges);
return cfg;
}
diff --git a/lib/Analysis/ArrayBoundChecker.cpp b/lib/Analysis/ArrayBoundChecker.cpp
index 3d95ab183471..49c86068265b 100644
--- a/lib/Analysis/ArrayBoundChecker.cpp
+++ b/lib/Analysis/ArrayBoundChecker.cpp
@@ -57,7 +57,8 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
// Get the size of the array.
DefinedOrUnknownSVal NumElements
- = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
+ = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+ ER->getValueType(C.getASTContext()));
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index eab7da7e8370..5b8aeae5d1c5 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -14,6 +14,7 @@
#include "clang/Analysis/Support/SaveAndRestore.h"
#include "clang/Analysis/CFG.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/GraphWriter.h"
@@ -70,6 +71,7 @@ class CFGBuilder {
CFGBlock* BreakTargetBlock;
CFGBlock* SwitchTerminatedBlock;
CFGBlock* DefaultCaseBlock;
+ CFGBlock* TryTerminatedBlock;
// LabelMap records the mapping from Label expressions to their blocks.
typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
@@ -88,10 +90,12 @@ public:
explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
Block(NULL), Succ(NULL),
ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
- SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) {}
+ SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
+ TryTerminatedBlock(NULL) {}
// buildCFG - Used by external clients to construct the CFG.
- CFG* buildCFG(Stmt *Statement, ASTContext *C);
+ CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, bool AddEHEdges,
+ bool AddScopes);
private:
// Visitors to walk an AST and construct the CFG.
@@ -106,9 +110,9 @@ private:
CFGBlock *VisitConditionalOperator(ConditionalOperator *C,
AddStmtChoice asc);
CFGBlock *VisitContinueStmt(ContinueStmt *C);
- CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S) { return NYS(); }
+ CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
- CFGBlock *VisitCXXTryStmt(CXXTryStmt *S) { return NYS(); }
+ CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
CFGBlock *VisitDeclStmt(DeclStmt *DS);
CFGBlock *VisitDeclSubExpr(Decl* D);
CFGBlock *VisitDefaultStmt(DefaultStmt *D);
@@ -139,6 +143,25 @@ private:
return Block;
}
+ CFGBlock *StartScope(Stmt *S, CFGBlock *B) {
+ if (!AddScopes)
+ return B;
+
+ if (B == 0)
+ B = createBlock();
+ B->StartScope(S, cfg->getBumpVectorContext());
+ return B;
+ }
+
+ void EndScope(Stmt *S) {
+ if (!AddScopes)
+ return;
+
+ if (Block == 0)
+ Block = createBlock();
+ Block->EndScope(S, cfg->getBumpVectorContext());
+ }
+
void autoCreateBlock() { if (!Block) Block = createBlock(); }
CFGBlock *createBlock(bool add_successor = true);
bool FinishBlock(CFGBlock* B);
@@ -186,6 +209,12 @@ private:
}
bool badCFG;
+
+ // True iff EH edges on CallExprs should be added to the CFG.
+ bool AddEHEdges;
+
+ // True iff scope start and scope end notes should be added to the CFG.
+ bool AddScopes;
};
// FIXME: Add support for dependent-sized array types in C++?
@@ -207,12 +236,15 @@ static VariableArrayType* FindVA(Type* t) {
/// body (compound statement). The ownership of the returned CFG is
/// transferred to the caller. If CFG construction fails, this method returns
/// NULL.
-CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
+CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C,
+ bool addehedges, bool AddScopes) {
+ AddEHEdges = addehedges;
Context = C;
assert(cfg.get());
if (!Statement)
return NULL;
+ this->AddScopes = AddScopes;
badCFG = false;
// Create an empty block that will serve as the exit block for the CFG. Since
@@ -224,6 +256,11 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
// Visit the statements and create the CFG.
CFGBlock* B = addStmt(Statement);
+
+ if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
+ // FIXME: Add code for base initializers and member initializers.
+ (void)CD;
+ }
if (!B)
B = Succ;
@@ -329,6 +366,15 @@ tryAgain:
case Stmt::ContinueStmtClass:
return VisitContinueStmt(cast<ContinueStmt>(S));
+ case Stmt::CXXCatchStmtClass:
+ return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
+
+ case Stmt::CXXThrowExprClass:
+ return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
+
+ case Stmt::CXXTryStmtClass:
+ return VisitCXXTryStmt(cast<CXXTryStmt>(S));
+
case Stmt::DeclStmtClass:
return VisitDeclStmt(cast<DeclStmt>(S));
@@ -356,9 +402,6 @@ tryAgain:
case Stmt::ObjCAtCatchStmtClass:
return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
- case Stmt::CXXThrowExprClass:
- return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
-
case Stmt::ObjCAtSynchronizedStmtClass:
return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
@@ -456,7 +499,7 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
} else {
- assert (B->getOpcode() == BinaryOperator::LAnd);
+ assert(B->getOpcode() == BinaryOperator::LAnd);
AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
}
@@ -504,6 +547,22 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
return Block;
}
+static bool CanThrow(Expr *E) {
+ QualType Ty = E->getType();
+ if (Ty->isFunctionPointerType())
+ Ty = Ty->getAs<PointerType>()->getPointeeType();
+ else if (Ty->isBlockPointerType())
+ Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
+
+ const FunctionType *FT = Ty->getAs<FunctionType>();
+ if (FT) {
+ if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
+ if (Proto->hasEmptyExceptionSpec())
+ return false;
+ }
+ return true;
+}
+
CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = false;
@@ -511,22 +570,47 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
NoReturn = true;
}
- if (FunctionDecl *FD = C->getDirectCallee())
+ bool AddEHEdge = false;
+
+ // Languages without exceptions are assumed to not throw.
+ if (Context->getLangOptions().Exceptions) {
+ if (AddEHEdges)
+ AddEHEdge = true;
+ }
+
+ if (FunctionDecl *FD = C->getDirectCallee()) {
if (FD->hasAttr<NoReturnAttr>())
NoReturn = true;
+ if (FD->hasAttr<NoThrowAttr>())
+ AddEHEdge = false;
+ }
- if (!NoReturn)
+ if (!CanThrow(C->getCallee()))
+ AddEHEdge = false;
+
+ if (!NoReturn && !AddEHEdge)
return VisitStmt(C, asc);
- if (Block && !FinishBlock(Block))
- return 0;
+ if (Block) {
+ Succ = Block;
+ if (!FinishBlock(Block))
+ return 0;
+ }
- // Create new block with no successor for the remaining pieces.
- Block = createBlock(false);
+ Block = createBlock(!NoReturn);
AppendStmt(Block, C, asc);
- // Wire this to the exit block directly.
- AddSuccessor(Block, &cfg->getExit());
+ if (NoReturn) {
+ // Wire this to the exit block directly.
+ AddSuccessor(Block, &cfg->getExit());
+ }
+ if (AddEHEdge) {
+ // Add exceptional edges.
+ if (TryTerminatedBlock)
+ AddSuccessor(Block, TryTerminatedBlock);
+ else
+ AddSuccessor(Block, &cfg->getExit());
+ }
return VisitChildren(C);
}
@@ -561,6 +645,8 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
+ EndScope(C);
+
CFGBlock* LastBlock = Block;
for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
@@ -570,6 +656,9 @@ CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
if (badCFG)
return NULL;
}
+
+ LastBlock = StartScope(C, LastBlock);
+
return LastBlock;
}
@@ -743,7 +832,7 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
CFGBlock* ThenBlock;
{
Stmt* Then = I->getThen();
- assert (Then);
+ assert(Then);
SaveAndRestore<CFGBlock*> sv(Succ);
Block = NULL;
ThenBlock = addStmt(Then);
@@ -919,12 +1008,12 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
// Now create the loop body.
{
- assert (F->getBody());
+ assert(F->getBody());
// Save the current values for Block, Succ, and continue and break targets
SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
- save_continue(ContinueTargetBlock),
- save_break(BreakTargetBlock);
+ save_continue(ContinueTargetBlock),
+ save_break(BreakTargetBlock);
// Create a new block to contain the (bottom) of the loop body.
Block = NULL;
@@ -1252,8 +1341,12 @@ CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
// Create the new block.
Block = createBlock(false);
- // The Exit block is the only successor.
- AddSuccessor(Block, &cfg->getExit());
+ if (TryTerminatedBlock)
+ // The current try statement is the only successor.
+ AddSuccessor(Block, TryTerminatedBlock);
+ else
+ // otherwise the Exit block is the only successor.
+ AddSuccessor(Block, &cfg->getExit());
// Add the statement to the block. This may create new blocks if S contains
// control-flow (short-circuit operations).
@@ -1301,12 +1394,12 @@ CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) {
// Process the loop body.
CFGBlock* BodyBlock = NULL;
{
- assert (D->getBody());
+ assert(D->getBody());
// Save the current values for Block, Succ, and continue and break targets
SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
- save_continue(ContinueTargetBlock),
- save_break(BreakTargetBlock);
+ save_continue(ContinueTargetBlock),
+ save_break(BreakTargetBlock);
// All continues within this loop should go to the condition block
ContinueTargetBlock = EntryConditionBlock;
@@ -1434,7 +1527,7 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
// When visiting the body, the case statements should automatically get linked
// up to the switch. We also don't keep a pointer to the body, since all
// control-flow from the switch goes to case/default statements.
- assert (Terminator->getBody() && "switch must contain a non-NULL body");
+ assert(Terminator->getBody() && "switch must contain a non-NULL body");
Block = NULL;
CFGBlock *BodyBlock = addStmt(Terminator->getBody());
if (Block) {
@@ -1448,7 +1541,7 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
// Add the terminator and condition in the switch block.
SwitchTerminatedBlock->setTerminator(Terminator);
- assert (Terminator->getCond() && "switch condition must be non-NULL");
+ assert(Terminator->getCond() && "switch condition must be non-NULL");
Block = SwitchTerminatedBlock;
Block = addStmt(Terminator->getCond());
@@ -1528,6 +1621,82 @@ CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) {
return DefaultCaseBlock;
}
+CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
+ // "try"/"catch" is a control-flow statement. Thus we stop processing the
+ // current block.
+ CFGBlock* TrySuccessor = NULL;
+
+ if (Block) {
+ if (!FinishBlock(Block))
+ return 0;
+ TrySuccessor = Block;
+ } else TrySuccessor = Succ;
+
+ CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
+
+ // Create a new block that will contain the try statement.
+ CFGBlock *NewTryTerminatedBlock = createBlock(false);
+ // Add the terminator in the try block.
+ NewTryTerminatedBlock->setTerminator(Terminator);
+
+ bool HasCatchAll = false;
+ for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) {
+ // The code after the try is the implicit successor.
+ Succ = TrySuccessor;
+ CXXCatchStmt *CS = Terminator->getHandler(h);
+ if (CS->getExceptionDecl() == 0) {
+ HasCatchAll = true;
+ }
+ Block = NULL;
+ CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
+ if (CatchBlock == 0)
+ return 0;
+ // Add this block to the list of successors for the block with the try
+ // statement.
+ AddSuccessor(NewTryTerminatedBlock, CatchBlock);
+ }
+ if (!HasCatchAll) {
+ if (PrevTryTerminatedBlock)
+ AddSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
+ else
+ AddSuccessor(NewTryTerminatedBlock, &cfg->getExit());
+ }
+
+ // The code after the try is the implicit successor.
+ Succ = TrySuccessor;
+
+ // Save the current "try" context.
+ SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock);
+ TryTerminatedBlock = NewTryTerminatedBlock;
+
+ assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
+ Block = NULL;
+ Block = addStmt(Terminator->getTryBlock());
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) {
+ // CXXCatchStmt are treated like labels, so they are the first statement in a
+ // block.
+
+ if (CS->getHandlerBlock())
+ addStmt(CS->getHandlerBlock());
+
+ CFGBlock* CatchBlock = Block;
+ if (!CatchBlock)
+ CatchBlock = createBlock();
+
+ CatchBlock->setLabel(CS);
+
+ if (!FinishBlock(CatchBlock))
+ return 0;
+
+ // We set Block to NULL to allow lazy creation of a new block (if necessary)
+ Block = NULL;
+
+ return CatchBlock;
+}
+
CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
// Lazily create the indirect-goto dispatch block if there isn't one already.
CFGBlock* IBlock = cfg->getIndirectGotoBlock();
@@ -1571,9 +1740,10 @@ CFGBlock* CFG::createBlock() {
/// buildCFG - Constructs a CFG from an AST. Ownership of the returned
/// CFG is returned to the caller.
-CFG* CFG::buildCFG(Stmt* Statement, ASTContext *C) {
+CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C,
+ bool AddEHEdges, bool AddScopes) {
CFGBuilder Builder;
- return Builder.buildCFG(Statement, C);
+ return Builder.buildCFG(D, Statement, C, AddEHEdges, AddScopes);
}
//===----------------------------------------------------------------------===//
@@ -1661,9 +1831,7 @@ CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) {
BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap);
BlkExprMapTy::iterator I = M->find(S);
-
- if (I == M->end()) return CFG::BlkExprNumTy();
- else return CFG::BlkExprNumTy(I->second);
+ return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second);
}
unsigned CFG::getNumBlkExprs() {
@@ -1692,7 +1860,6 @@ CFG::~CFG() {
namespace {
class StmtPrinterHelper : public PrinterHelper {
-
typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
StmtMapTy StmtMap;
signed CurrentBlock;
@@ -1724,10 +1891,11 @@ public:
return false;
if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock
- && I->second.second == CurrentStmt)
+ && I->second.second == CurrentStmt) {
return false;
+ }
- OS << "[B" << I->second.first << "." << I->second.second << "]";
+ OS << "[B" << I->second.first << "." << I->second.second << "]";
return true;
}
};
@@ -1741,7 +1909,6 @@ class CFGBlockTerminatorPrint
llvm::raw_ostream& OS;
StmtPrinterHelper* Helper;
PrintingPolicy Policy;
-
public:
CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper,
const PrintingPolicy &Policy)
@@ -1759,22 +1926,27 @@ public:
void VisitForStmt(ForStmt* F) {
OS << "for (" ;
- if (F->getInit()) OS << "...";
+ if (F->getInit())
+ OS << "...";
OS << "; ";
- if (Stmt* C = F->getCond()) C->printPretty(OS, Helper, Policy);
+ if (Stmt* C = F->getCond())
+ C->printPretty(OS, Helper, Policy);
OS << "; ";
- if (F->getInc()) OS << "...";
+ if (F->getInc())
+ OS << "...";
OS << ")";
}
void VisitWhileStmt(WhileStmt* W) {
OS << "while " ;
- if (Stmt* C = W->getCond()) C->printPretty(OS, Helper, Policy);
+ if (Stmt* C = W->getCond())
+ C->printPretty(OS, Helper, Policy);
}
void VisitDoStmt(DoStmt* D) {
OS << "do ... while ";
- if (Stmt* C = D->getCond()) C->printPretty(OS, Helper, Policy);
+ if (Stmt* C = D->getCond())
+ C->printPretty(OS, Helper, Policy);
}
void VisitSwitchStmt(SwitchStmt* Terminator) {
@@ -1782,6 +1954,10 @@ public:
Terminator->getCond()->printPretty(OS, Helper, Policy);
}
+ void VisitCXXTryStmt(CXXTryStmt* CS) {
+ OS << "try ...";
+ }
+
void VisitConditionalOperator(ConditionalOperator* C) {
C->getCond()->printPretty(OS, Helper, Policy);
OS << " ? ... : ...";
@@ -1826,7 +2002,18 @@ public:
static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
- Stmt* Terminator) {
+ const CFGElement &E) {
+ Stmt *Terminator = E;
+
+ if (E.asStartScope()) {
+ OS << "start scope\n";
+ return;
+ }
+ if (E.asEndScope()) {
+ OS << "end scope\n";
+ return;
+ }
+
if (Helper) {
// special printing for statement-expressions.
if (StmtExpr* SE = dyn_cast<StmtExpr>(Terminator)) {
@@ -1876,14 +2063,14 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
OS << " ]\n";
// Print the label of this block.
- if (Stmt* Terminator = const_cast<Stmt*>(B.getLabel())) {
+ if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) {
if (print_edges)
OS << " ";
- if (LabelStmt* L = dyn_cast<LabelStmt>(Terminator))
+ if (LabelStmt* L = dyn_cast<LabelStmt>(Label))
OS << L->getName();
- else if (CaseStmt* C = dyn_cast<CaseStmt>(Terminator)) {
+ else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
OS << "case ";
C->getLHS()->printPretty(OS, Helper,
PrintingPolicy(Helper->getLangOpts()));
@@ -1892,9 +2079,18 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
C->getRHS()->printPretty(OS, Helper,
PrintingPolicy(Helper->getLangOpts()));
}
- } else if (isa<DefaultStmt>(Terminator))
+ } else if (isa<DefaultStmt>(Label))
OS << "default";
- else
+ else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
+ OS << "catch (";
+ if (CS->getExceptionDecl())
+ CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()),
+ 0);
+ else
+ OS << "...";
+ OS << ")";
+
+ } else
assert(false && "Invalid label statement in CFGBlock.");
OS << ":\n";
diff --git a/lib/Analysis/CastToStructChecker.cpp b/lib/Analysis/CastToStructChecker.cpp
index a3663421a082..219c09f6ab7a 100644
--- a/lib/Analysis/CastToStructChecker.cpp
+++ b/lib/Analysis/CastToStructChecker.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This files defines CastToStructChecker, a builtin checker that checks for
-// assignment of a fixed address to a pointer.
+// cast from non-struct pointer to struct pointer.
// This check corresponds to CWE-588.
//
//===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 40c12c9fec84..8f8d859e0ca0 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -2173,8 +2173,8 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue){
+void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst, bool asLValue) {
ExplodedNodeSet S1;
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
@@ -2191,14 +2191,6 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet S2;
CheckerVisit(CastE, S2, S1, true);
- // Check for casting to "void".
- if (T->isVoidType()) {
- assert(!asLValue);
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
- Dst.Add(*I);
- return;
- }
-
// If we are evaluating the cast in an lvalue context, we implicitly want
// the cast to evaluate to a location.
if (asLValue) {
@@ -2207,13 +2199,51 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy));
}
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
- ExplodedNode* N = *I;
- const GRState* state = GetState(N);
- SVal V = state->getSVal(Ex);
- const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy);
- state = Res.getState()->BindExpr(CastE, Res.getSVal());
- MakeNode(Dst, CastE, N, state);
+ switch (CastE->getCastKind()) {
+ case CastExpr::CK_ToVoid:
+ assert(!asLValue);
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
+ Dst.Add(*I);
+ return;
+
+ case CastExpr::CK_NoOp:
+ case CastExpr::CK_FunctionToPointerDecay:
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ // Copy the SVal of Ex to CastE.
+ ExplodedNode *N = *I;
+ const GRState *state = GetState(N);
+ SVal V = state->getSVal(Ex);
+ state = state->BindExpr(CastE, V);
+ MakeNode(Dst, CastE, N, state);
+ }
+ return;
+
+ case CastExpr::CK_Unknown:
+ case CastExpr::CK_ArrayToPointerDecay:
+ case CastExpr::CK_BitCast:
+ case CastExpr::CK_IntegralCast:
+ case CastExpr::CK_IntegralToPointer:
+ case CastExpr::CK_PointerToIntegral:
+ case CastExpr::CK_IntegralToFloating:
+ case CastExpr::CK_FloatingToIntegral:
+ case CastExpr::CK_FloatingCast:
+ case CastExpr::CK_AnyPointerToObjCPointerCast:
+ case CastExpr::CK_AnyPointerToBlockPointerCast:
+ case CastExpr::CK_DerivedToBase:
+ // Delegate to SValuator to process.
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ ExplodedNode* N = *I;
+ const GRState* state = GetState(N);
+ SVal V = state->getSVal(Ex);
+ const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy);
+ state = Res.getState()->BindExpr(CastE, Res.getSVal());
+ MakeNode(Dst, CastE, N, state);
+ }
+ return;
+
+ default:
+ llvm::errs() << "Cast kind " << CastE->getCastKind() << " not handled.\n";
+ assert(0);
}
}
@@ -2952,13 +2982,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Perform a load (the LHS). This performs the checks for
// null dereferences, and so on.
- ExplodedNodeSet Tmp3;
+ ExplodedNodeSet Tmp4;
SVal location = state->getSVal(LHS);
- EvalLoad(Tmp3, LHS, *I2, state, location);
+ EvalLoad(Tmp4, LHS, *I2, state, location);
- for (ExplodedNodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3;
- ++I3) {
- state = GetState(*I3);
+ for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
+ ++I4) {
+ state = GetState(*I4);
SVal V = state->getSVal(LHS);
// Get the computation type.
@@ -3008,7 +3038,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
llvm::tie(state, LHSVal) = SVator.EvalCast(Result, state, LTy, CTy);
}
- EvalStore(Tmp3, B, LHS, *I3, state->BindExpr(B, Result),
+ EvalStore(Tmp3, B, LHS, *I4, state->BindExpr(B, Result),
location, LHSVal);
}
}
diff --git a/lib/Analysis/MallocChecker.cpp b/lib/Analysis/MallocChecker.cpp
index fab73ee7b104..28f4db788068 100644
--- a/lib/Analysis/MallocChecker.cpp
+++ b/lib/Analysis/MallocChecker.cpp
@@ -72,7 +72,7 @@ public:
private:
void MallocMem(CheckerContext &C, const CallExpr *CE);
const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
- const GRState *state);
+ const Expr *SizeEx, const GRState *state);
void FreeMem(CheckerContext &C, const CallExpr *CE);
const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
const GRState *state);
@@ -136,18 +136,24 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
}
void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
- const GRState *state = MallocMemAux(C, CE, C.getState());
+ const GRState *state = MallocMemAux(C, CE, CE->getArg(0), C.getState());
C.addTransition(state);
}
const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
const CallExpr *CE,
+ const Expr *SizeEx,
const GRState *state) {
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
ValueManager &ValMgr = C.getValueManager();
SVal RetVal = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
+ SVal Size = state->getSVal(SizeEx);
+
+ state = C.getEngine().getStoreManager().setExtent(state, RetVal.getAsRegion(),
+ Size);
+
state = state->BindExpr(CE, RetVal);
SymbolRef Sym = RetVal.getAsLocSymbol();
@@ -170,7 +176,12 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
assert(Sym);
const RefState *RS = state->get<RegionState>(Sym);
- assert(RS);
+
+ // If the symbol has not been tracked, return. This is possible when free() is
+ // called on a pointer that does not get its pointee directly from malloc().
+ // Full support of this requires inter-procedural analysis.
+ if (!RS)
+ return state;
// Check double free.
if (RS->isReleased()) {
@@ -211,7 +222,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
if (Sym)
stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE));
- const GRState *stateMalloc = MallocMemAux(C, CE, stateEqual);
+ const GRState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1), stateEqual);
C.addTransition(stateMalloc);
}
@@ -232,7 +243,8 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero);
if (stateFree) {
// FIXME: We should copy the content of the original buffer.
- const GRState *stateRealloc = MallocMemAux(C, CE, stateFree);
+ const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
+ stateFree);
C.addTransition(stateRealloc);
}
}
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 9b5b44be6427..a735ed94578e 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -21,6 +21,7 @@
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Support/Optional.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/CharUnits.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/ImmutableList.h"
@@ -423,9 +424,9 @@ public:
// Region "extents".
//===------------------------------------------------------------------===//
- const GRState *setExtent(const GRState *state, const MemRegion* R, SVal Extent);
+ const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent);
DefinedOrUnknownSVal getSizeInElements(const GRState *state,
- const MemRegion* R);
+ const MemRegion* R, QualType EleTy);
//===------------------------------------------------------------------===//
// Utility methods.
@@ -767,7 +768,8 @@ SVal RegionStoreManager::getLValueElement(QualType elementType, SVal Offset,
//===----------------------------------------------------------------------===//
DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
- const MemRegion *R) {
+ const MemRegion *R,
+ QualType EleTy) {
switch (R->getKind()) {
case MemRegion::CXXThisRegionKind:
@@ -793,10 +795,25 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
case MemRegion::ElementRegionKind:
case MemRegion::FieldRegionKind:
case MemRegion::ObjCIvarRegionKind:
- case MemRegion::SymbolicRegionKind:
case MemRegion::CXXObjectRegionKind:
return UnknownVal();
+ case MemRegion::SymbolicRegionKind: {
+ const SVal *Size = state->get<RegionExtents>(R);
+ if (!Size)
+ return UnknownVal();
+ const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(Size);
+ if (!CI)
+ return UnknownVal();
+
+ CharUnits RegionSize =
+ CharUnits::fromQuantity(CI->getValue().getSExtValue());
+ CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
+ assert(RegionSize % EleSize == 0);
+
+ return ValMgr.makeIntVal(RegionSize / EleSize, false);
+ }
+
case MemRegion::StringRegionKind: {
const StringLiteral* Str = cast<StringRegion>(R)->getStringLiteral();
// We intentionally made the size value signed because it participates in
diff --git a/lib/Analysis/ReturnPointerRangeChecker.cpp b/lib/Analysis/ReturnPointerRangeChecker.cpp
index ab0fcab4219e..b0350cb576ff 100644
--- a/lib/Analysis/ReturnPointerRangeChecker.cpp
+++ b/lib/Analysis/ReturnPointerRangeChecker.cpp
@@ -65,7 +65,8 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
// into a common place.
DefinedOrUnknownSVal NumElements
- = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
+ = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+ ER->getValueType(C.getASTContext()));
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
diff --git a/lib/Basic/Makefile b/lib/Basic/Makefile
index 5bd4314f45cd..f7335789384f 100644
--- a/lib/Basic/Makefile
+++ b/lib/Basic/Makefile
@@ -17,10 +17,13 @@ BUILD_ARCHIVE = 1
CXXFLAGS = -fno-rtti
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
+ifdef CLANG_VENDOR
+CPPFLAGS += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
+endif
include $(LEVEL)/Makefile.common
-SVN_REVISION := $(shell cd $(PROJ_SRC_DIR)/../.. && svnversion)
+SVN_REVISION := $(shell $(LLVM_SRC_ROOT)/utils/GetSourceVersion $(PROJ_SRC_DIR)/../..)
CPP.Defines += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include \
-DSVN_REVISION='"$(SVN_REVISION)"'
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index bba2c3ffc41f..ea076ae0bbfc 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -16,9 +16,9 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetOptions.h"
-#include "clang/Frontend/Utils.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index ba31544384cb..b1b250f82933 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -10,13 +10,17 @@
// This file defines several version-related utility functions for Clang.
//
//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Version.h"
+#include "llvm/Support/raw_ostream.h"
#include <cstring>
#include <cstdlib>
+
using namespace std;
namespace clang {
-const char *getClangSubversionPath() {
+llvm::StringRef getClangRepositoryPath() {
static const char *Path = 0;
if (Path)
return Path;
@@ -41,13 +45,43 @@ const char *getClangSubversionPath() {
}
-unsigned getClangSubversionRevision() {
+llvm::StringRef getClangRevision() {
#ifndef SVN_REVISION
// Subversion was not available at build time?
- return 0;
+ return llvm::StringRef();
#else
- return strtol(SVN_REVISION, 0, 10);
+ static std::string revision;
+ if (revision.empty()) {
+ llvm::raw_string_ostream OS(revision);
+ OS << strtol(SVN_REVISION, 0, 10);
+ }
+ return revision;
#endif
}
+llvm::StringRef getClangFullRepositoryVersion() {
+ static std::string buf;
+ if (buf.empty()) {
+ llvm::raw_string_ostream OS(buf);
+ OS << getClangRepositoryPath();
+ llvm::StringRef Revision = getClangRevision();
+ if (!Revision.empty())
+ OS << ' ' << Revision;
+ }
+ return buf;
+}
+
+const char *getClangFullVersion() {
+ static std::string buf;
+ if (buf.empty()) {
+ llvm::raw_string_ostream OS(buf);
+#ifdef CLANG_VENDOR
+ OS << CLANG_VENDOR;
+#endif
+ OS << "clang version " CLANG_VERSION_STRING " ("
+ << getClangFullRepositoryVersion() << ')';
+ }
+ return buf.c_str();
+}
+
} // end namespace clang
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 1fa422f29e1c..ca5b6fa97c26 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -18,7 +18,6 @@
#include "llvm/Module.h"
#include "llvm/Target/TargetData.h"
#include <algorithm>
-#include <cstdio>
using namespace clang;
using namespace CodeGen;
@@ -221,11 +220,10 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
C = llvm::ConstantStruct::get(VMContext, Elts, false);
- char Name[32];
- sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
- llvm::GlobalValue::InternalLinkage,
- C, Name);
+ llvm::GlobalValue::InternalLinkage, C,
+ "__block_holder_tmp_" +
+ llvm::Twine(CGM.getGlobalUniqueCount()));
QualType BPT = BE->getType();
C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
return C;
@@ -747,13 +745,12 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
const CGFunctionInfo &FI =
CGM.getTypes().getFunctionInfo(ResultType, Args);
- std::string Name = std::string("__") + Info.Name + "_block_invoke_";
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic);
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- Name,
+ llvm::Twine("__") + Info.Name + "_block_invoke_",
&CGM.getModule());
CGM.SetInternalFunctionAttributes(BD, Fn, FI);
@@ -875,14 +872,12 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
- std::string Name = std::string("__copy_helper_block_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- Name,
- &CGM.getModule());
+ "__copy_helper_block_", &CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__copy_helper_block_");
@@ -958,14 +953,12 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
- std::string Name = std::string("__destroy_helper_block_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- Name,
- &CGM.getModule());
+ "__destroy_helper_block_", &CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__destroy_helper_block_");
@@ -1042,7 +1035,6 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
const CGFunctionInfo &FI =
CGM.getTypes().getFunctionInfo(R, Args);
- std::string Name = std::string("__Block_byref_id_object_copy_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
@@ -1050,8 +1042,7 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
// internal linkage.
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- Name,
- &CGM.getModule());
+ "__Block_byref_id_object_copy_", &CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__Block_byref_id_object_copy_");
@@ -1107,7 +1098,6 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
const CGFunctionInfo &FI =
CGM.getTypes().getFunctionInfo(R, Args);
- std::string Name = std::string("__Block_byref_id_object_dispose_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
@@ -1115,7 +1105,7 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
// internal linkage.
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- Name,
+ "__Block_byref_id_object_dispose_",
&CGM.getModule());
IdentifierInfo *II
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 866c58780b9c..f11d52e4334c 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -72,6 +72,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
switch (BuiltinID) {
default: break; // Handle intrinsics and libm functions below.
case Builtin::BI__builtin___CFStringMakeConstantString:
+ case Builtin::BI__builtin___NSStringMakeConstantString:
return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0));
case Builtin::BI__builtin_stdarg_start:
case Builtin::BI__builtin_va_start:
@@ -556,6 +557,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(0);
}
+ case Builtin::BI__builtin_llvm_memory_barrier: {
+ Value *C[5] = {
+ EmitScalarExpr(E->getArg(0)),
+ EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)),
+ EmitScalarExpr(E->getArg(3)),
+ EmitScalarExpr(E->getArg(4))
+ };
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::memory_barrier), C, C + 5);
+ return RValue::get(0);
+ }
+
// Library functions with special handling.
case Builtin::BIsqrt:
case Builtin::BIsqrtf:
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index ab3fece90f50..a822ca2b7417 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -394,10 +394,8 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
if (BitwiseAssign)
EmitAggregateCopy(Dest, Src, Ty);
else {
- bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(),
- MD);
- assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign");
- (void)hasCopyAssign;
+ BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
+ assert(MD && "EmitClassAggrCopyAssignment - No user assign");
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *LTy =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
@@ -410,8 +408,10 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
MD->getThisType(getContext())));
// Push the Src ptr.
- CallArgs.push_back(std::make_pair(RValue::get(Src),
- MD->getParamDecl(0)->getType()));
+ QualType SrcTy = MD->getParamDecl(0)->getType();
+ RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
+ RValue::getAggregate(Src);
+ CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
Callee, ReturnValueSlot(), CallArgs, MD);
@@ -531,10 +531,8 @@ void CodeGenFunction::EmitClassCopyAssignment(
}
const CXXMethodDecl *MD = 0;
- bool ConstCopyAssignOp = BaseClassDecl->hasConstCopyAssignment(getContext(),
- MD);
- assert(ConstCopyAssignOp && "EmitClassCopyAssignment - missing copy assign");
- (void)ConstCopyAssignOp;
+ BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
+ assert(MD && "EmitClassCopyAssignment - missing copy assign");
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *LTy =
@@ -548,8 +546,10 @@ void CodeGenFunction::EmitClassCopyAssignment(
MD->getThisType(getContext())));
// Push the Src ptr.
- CallArgs.push_back(std::make_pair(RValue::get(Src),
- MD->getParamDecl(0)->getType()));
+ QualType SrcTy = MD->getParamDecl(0)->getType();
+ RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
+ RValue::getAggregate(Src);
+ CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
QualType ResultType =
MD->getType()->getAs<FunctionType>()->getResultType();
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index ab8f6637d6ce..1ffad3edcac7 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -460,58 +460,15 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
return DbgTy;
}
-/// CreateType - get structure or union type.
-llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
- llvm::DICompileUnit Unit) {
- RecordDecl *Decl = Ty->getDecl();
-
- unsigned Tag;
- if (Decl->isStruct())
- Tag = llvm::dwarf::DW_TAG_structure_type;
- else if (Decl->isUnion())
- Tag = llvm::dwarf::DW_TAG_union_type;
- else {
- assert(Decl->isClass() && "Unknown RecordType!");
- Tag = llvm::dwarf::DW_TAG_class_type;
- }
-
+/// CollectRecordFields - A helper function to collect debug info for
+/// record fields. This is used while creating debug info entry for a Record.
+void CGDebugInfo::
+CollectRecordFields(const RecordDecl *Decl,
+ llvm::DICompileUnit Unit,
+ llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) {
+ unsigned FieldNo = 0;
SourceManager &SM = CGM.getContext().getSourceManager();
-
- // Get overall information about the record type for the debug info.
- PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
- llvm::DICompileUnit DefUnit;
- unsigned Line = 0;
- if (!PLoc.isInvalid()) {
- DefUnit = getOrCreateCompileUnit(Decl->getLocation());
- Line = PLoc.getLine();
- }
-
- // Records and classes and unions can all be recursive. To handle them, we
- // first generate a debug descriptor for the struct as a forward declaration.
- // Then (if it is a definition) we go through and get debug info for all of
- // its members. Finally, we create a descriptor for the complete type (which
- // may refer to the forward decl if the struct is recursive) and replace all
- // uses of the forward declaration with the final definition.
- llvm::DICompositeType FwdDecl =
- DebugFactory.CreateCompositeType(Tag, Unit, Decl->getName(),
- DefUnit, Line, 0, 0, 0, 0,
- llvm::DIType(), llvm::DIArray());
-
- // If this is just a forward declaration, return it.
- if (!Decl->getDefinition(CGM.getContext()))
- return FwdDecl;
-
- llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode();
- // Otherwise, insert it into the TypeCache so that recursive uses will find
- // it.
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
-
- // Convert all the elements.
- llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
-
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(Decl);
-
- unsigned FieldNo = 0;
for (RecordDecl::field_iterator I = Decl->field_begin(),
E = Decl->field_end();
I != E; ++I, ++FieldNo) {
@@ -560,6 +517,125 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
}
+}
+
+/// CollectCXXMemberFunctions - A helper function to collect debug info for
+/// C++ member functions.This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
+ llvm::DICompileUnit Unit,
+ llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
+ llvm::DICompositeType &RecordTy) {
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ for(CXXRecordDecl::method_iterator I = Decl->method_begin(),
+ E = Decl->method_end(); I != E; ++I) {
+ CXXMethodDecl *Method = *I;
+ llvm::StringRef MethodName;
+ llvm::StringRef MethodLinkageName;
+ llvm::DIType MethodTy = getOrCreateType(Method->getType(), Unit);
+ if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(Method)) {
+ if (CDecl->isImplicit())
+ continue;
+ MethodName = Decl->getName();
+ // FIXME : Find linkage name.
+ } else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(Method)) {
+ if (DDecl->isImplicit())
+ continue;
+ MethodName = getFunctionName(Method);
+ // FIXME : Find linkage name.
+ } else {
+ if (Method->isImplicit())
+ continue;
+ // regular method
+ MethodName = getFunctionName(Method);
+ MethodLinkageName = CGM.getMangledName(Method);
+ }
+
+ // Get the location for the method.
+ SourceLocation MethodDefLoc = Method->getLocation();
+ PresumedLoc PLoc = SM.getPresumedLoc(MethodDefLoc);
+ llvm::DICompileUnit MethodDefUnit;
+ unsigned MethodLine = 0;
+
+ if (!PLoc.isInvalid()) {
+ MethodDefUnit = getOrCreateCompileUnit(MethodDefLoc);
+ MethodLine = PLoc.getLine();
+ }
+
+ llvm::DISubprogram SP =
+ DebugFactory.CreateSubprogram(RecordTy , MethodName, MethodName,
+ MethodLinkageName,
+ MethodDefUnit, MethodLine,
+ MethodTy, false,
+ Method->isThisDeclarationADefinition(),
+ 0 /*Virtuality*/, 0 /*VIndex*/,
+ llvm::DIType() /*ContainingType*/);
+ if (Method->isThisDeclarationADefinition())
+ SPCache[cast<FunctionDecl>(Method)] = llvm::WeakVH(SP.getNode());
+ EltTys.push_back(SP);
+ }
+}
+
+/// CreateType - get structure or union type.
+llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
+ llvm::DICompileUnit Unit) {
+ RecordDecl *Decl = Ty->getDecl();
+
+ unsigned Tag;
+ if (Decl->isStruct())
+ Tag = llvm::dwarf::DW_TAG_structure_type;
+ else if (Decl->isUnion())
+ Tag = llvm::dwarf::DW_TAG_union_type;
+ else {
+ assert(Decl->isClass() && "Unknown RecordType!");
+ Tag = llvm::dwarf::DW_TAG_class_type;
+ }
+
+ SourceManager &SM = CGM.getContext().getSourceManager();
+
+ // Get overall information about the record type for the debug info.
+ PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
+ llvm::DICompileUnit DefUnit;
+ unsigned Line = 0;
+ if (!PLoc.isInvalid()) {
+ DefUnit = getOrCreateCompileUnit(Decl->getLocation());
+ Line = PLoc.getLine();
+ }
+
+ // Records and classes and unions can all be recursive. To handle them, we
+ // first generate a debug descriptor for the struct as a forward declaration.
+ // Then (if it is a definition) we go through and get debug info for all of
+ // its members. Finally, we create a descriptor for the complete type (which
+ // may refer to the forward decl if the struct is recursive) and replace all
+ // uses of the forward declaration with the final definition.
+
+ // A Decl->getName() is not unique. However, the debug info descriptors
+ // are uniqued. The debug info descriptor describing record's context is
+ // necessary to keep two Decl's descriptor unique if their name match.
+ // FIXME : Use RecordDecl's DeclContext's descriptor. As a temp. step
+ // use type's name in FwdDecl.
+ std::string STy = QualType(Ty, 0).getAsString();
+ llvm::DICompositeType FwdDecl =
+ DebugFactory.CreateCompositeType(Tag, Unit, STy.c_str(),
+ DefUnit, Line, 0, 0, 0, 0,
+ llvm::DIType(), llvm::DIArray());
+
+ // If this is just a forward declaration, return it.
+ if (!Decl->getDefinition(CGM.getContext()))
+ return FwdDecl;
+
+ llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode();
+ // Otherwise, insert it into the TypeCache so that recursive uses will find
+ // it.
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
+
+ // Convert all the elements.
+ llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
+
+ CollectRecordFields(Decl, Unit, EltTys);
+ if (CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(Decl))
+ CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
llvm::DIArray Elements =
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
@@ -1000,18 +1076,27 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
const Decl *D = GD.getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // If there is a DISubprogram for this function available then use it.
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
+ FI = SPCache.find(FD);
+ if (FI != SPCache.end()) {
+ llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(FI->second));
+ if (!SP.isNull() && SP.isSubprogram() && SP.isDefinition()) {
+ RegionStack.push_back(SP.getNode());
+ return;
+ }
+ }
Name = getFunctionName(FD);
- if (Name[0] == '\01')
+ if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
// Use mangled name as linkage name for c/c++ functions.
LinkageName = CGM.getMangledName(GD);
} else {
// Use llvm function name as linkage name.
Name = Fn->getName();
- // Skip the asm prefix if it exists.
- if (Name[0] == '\01')
- Name = Name.substr(1);
LinkageName = Name;
+ if (!Name.empty() && Name[0] == '\01')
+ Name = Name.substr(1);
}
// It is expected that CurLoc is set before using EmitFunctionStart.
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 8e8898805751..fddd23b4e9c3 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -64,6 +64,8 @@ class CGDebugInfo {
/// constructed on demand. For example, C++ destructors, C++ operators etc..
llvm::BumpPtrAllocator FunctionNames;
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
+
/// Helper functions for getOrCreateType.
llvm::DIType CreateType(const BuiltinType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const ComplexType *Ty, llvm::DICompileUnit U);
@@ -85,6 +87,12 @@ class CGDebugInfo {
llvm::DIType CreatePointerLikeType(unsigned Tag,
const Type *Ty, QualType PointeeTy,
llvm::DICompileUnit U);
+ void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
+ llvm::DICompileUnit U,
+ llvm::SmallVectorImpl<llvm::DIDescriptor> &E,
+ llvm::DICompositeType &T);
+ void CollectRecordFields(const RecordDecl *Decl, llvm::DICompileUnit U,
+ llvm::SmallVectorImpl<llvm::DIDescriptor> &E);
public:
CGDebugInfo(CodeGenModule &CGM);
~CGDebugInfo();
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index dec06e295338..7d5b3da0b6c6 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -742,7 +742,8 @@ public:
return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
case Expr::ObjCStringLiteralClass: {
ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
- llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(SL);
+ llvm::Constant *C =
+ CGM.getObjCRuntime().GenerateConstantString(SL->getString());
return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}
case Expr::PredefinedExprClass: {
@@ -764,11 +765,18 @@ public:
}
case Expr::CallExprClass: {
CallExpr* CE = cast<CallExpr>(E);
- if (CE->isBuiltinCall(CGM.getContext()) !=
- Builtin::BI__builtin___CFStringMakeConstantString)
+ unsigned builtin = CE->isBuiltinCall(CGM.getContext());
+ if (builtin !=
+ Builtin::BI__builtin___CFStringMakeConstantString &&
+ builtin !=
+ Builtin::BI__builtin___NSStringMakeConstantString)
break;
const Expr *Arg = CE->getArg(0)->IgnoreParenCasts();
const StringLiteral *Literal = cast<StringLiteral>(Arg);
+ if (builtin ==
+ Builtin::BI__builtin___NSStringMakeConstantString) {
+ return CGM.getObjCRuntime().GenerateConstantString(Literal);
+ }
// FIXME: need to deal with UCN conversion issues.
return CGM.GetAddrOfConstantCFString(Literal);
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index ac391d99a150..896d2207ea4b 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -26,7 +26,8 @@ using namespace CodeGen;
/// Emits an instance of NSConstantString representing the object.
llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
{
- llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(E);
+ llvm::Constant *C =
+ CGM.getObjCRuntime().GenerateConstantString(E->getString());
// FIXME: This bitcast should just be made an invariant on the Runtime.
return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index e7a2093aa2e4..77be9fb58231 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -124,7 +124,7 @@ private:
void EmitClassRef(const std::string &className);
public:
CGObjCGNU(CodeGen::CodeGenModule &cgm);
- virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *);
+ virtual llvm::Constant *GenerateConstantString(const StringLiteral *);
virtual CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
@@ -240,15 +240,23 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
Zeros[1] = Zeros[0];
NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
// Get the selector Type.
- SelectorTy = cast<llvm::PointerType>(
- CGM.getTypes().ConvertType(CGM.getContext().getObjCSelType()));
+ QualType selTy = CGM.getContext().getObjCSelType();
+ if (QualType() == selTy) {
+ SelectorTy = PtrToInt8Ty;
+ } else {
+ SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy));
+ }
PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
PtrTy = PtrToInt8Ty;
// Object type
ASTIdTy = CGM.getContext().getObjCIdType();
- IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
+ if (QualType() == ASTIdTy) {
+ IdTy = PtrToInt8Ty;
+ } else {
+ IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
+ }
// IMP type
std::vector<const llvm::Type*> IMPArgs;
@@ -348,12 +356,9 @@ llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
}
/// Generate an NSConstantString object.
-//TODO: In case there are any crazy people still using the GNU runtime without
-//an OpenStep implementation, this should let them select their own class for
-//constant strings.
-llvm::Constant *CGObjCGNU::GenerateConstantString(const ObjCStringLiteral *SL) {
- std::string Str(SL->getString()->getStrData(),
- SL->getString()->getByteLength());
+llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
+ std::string Str(SL->getStrData(), SL->getByteLength());
+
std::vector<llvm::Constant*> Ivars;
Ivars.push_back(NULLPtr);
Ivars.push_back(MakeConstantString(Str));
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 727746fbbce7..137ea51721c7 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -952,7 +952,7 @@ public:
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
CGM(cgm), VMContext(cgm.getLLVMContext()) { }
- virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *SL);
+ virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD=0);
@@ -1454,8 +1454,8 @@ llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
*/
llvm::Constant *CGObjCCommonMac::GenerateConstantString(
- const ObjCStringLiteral *SL) {
- return CGM.GetAddrOfConstantCFString(SL->getString());
+ const StringLiteral *SL) {
+ return CGM.GetAddrOfConstantCFString(SL);
}
/// Generates a message send where the super is the receiver. This is
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index 6b4556239723..ff5d40bfbc87 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -106,7 +106,7 @@ public:
const ObjCMethodDecl *Method) = 0;
/// Generate a constant string object.
- virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *) = 0;
+ virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0;
/// Generate a category. A category contains a list of methods (and
/// accompanying metadata) and a list of protocols.
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
new file mode 100644
index 000000000000..9714bd9d9678
--- /dev/null
+++ b/lib/CodeGen/CGVTT.cpp
@@ -0,0 +1,398 @@
+//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of VTTs (vtable tables).
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "clang/AST/RecordLayout.h"
+using namespace clang;
+using namespace CodeGen;
+
+#define D1(x)
+
+namespace {
+class VTTBuilder {
+ /// Inits - The list of values built for the VTT.
+ std::vector<llvm::Constant *> &Inits;
+ /// Class - The most derived class that this vtable is being built for.
+ const CXXRecordDecl *Class;
+ CodeGenModule &CGM; // Per-module state.
+ llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
+ /// BLayout - Layout for the most derived class that this vtable is being
+ /// built for.
+ const ASTRecordLayout &BLayout;
+ CGVtableInfo::AddrMap_t &AddressPoints;
+ // vtbl - A pointer to the vtable for Class.
+ llvm::Constant *ClassVtbl;
+ llvm::LLVMContext &VMContext;
+
+ /// SeenVBasesInSecondary - The seen virtual bases when building the
+ /// secondary virtual pointers.
+ llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary;
+
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
+
+ bool GenerateDefinition;
+
+ llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
+ llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
+ CtorVtableAddressPoints;
+
+ llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
+ if (!GenerateDefinition)
+ return 0;
+
+ llvm::Constant *&CtorVtable = CtorVtables[Base];
+ if (!CtorVtable) {
+ // Build the vtable.
+ CGVtableInfo::CtorVtableInfo Info
+ = CGM.getVtableInfo().getCtorVtable(Class, Base);
+
+ CtorVtable = Info.Vtable;
+
+ // Add the address points for this base.
+ for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
+ Info.AddressPoints.begin(), E = Info.AddressPoints.end();
+ I != E; ++I) {
+ uint64_t &AddressPoint =
+ CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)];
+
+ // Check if we already have the address points for this base.
+ if (AddressPoint)
+ break;
+
+ // Otherwise, insert it.
+ AddressPoint = I->second;
+ }
+ }
+
+ return CtorVtable;
+ }
+
+
+ /// BuildVtablePtr - Build up a referene to the given secondary vtable
+ llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
+ const CXXRecordDecl *VtableClass,
+ const CXXRecordDecl *RD,
+ uint64_t Offset) {
+ if (!GenerateDefinition)
+ return 0;
+
+ uint64_t AddressPoint;
+
+ if (VtableClass != Class) {
+ // We have a ctor vtable, look for the address point in the ctor vtable
+ // address points.
+ AddressPoint =
+ CtorVtableAddressPoints[std::make_pair(VtableClass,
+ BaseSubobject(RD, Offset))];
+ } else {
+ AddressPoint =
+ (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
+ }
+
+ // FIXME: We can never have 0 address point. Do this for now so gepping
+ // retains the same structure. Later we'll just assert.
+ if (AddressPoint == 0)
+ AddressPoint = 1;
+ D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
+ RD->getNameAsCString(), VtblClass->getNameAsCString(),
+ Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
+
+ llvm::Value *Idxs[] = {
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
+ };
+
+ llvm::Constant *Init =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+ return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
+ }
+
+ /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
+ /// current offset in bits to the object we're working on.
+ void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
+ const CXXRecordDecl *VtblClass, uint64_t Offset=0,
+ bool MorallyVirtual=false) {
+ if (RD->getNumVBases() == 0 && ! MorallyVirtual)
+ return;
+
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+
+ // We only want to visit each virtual base once.
+ if (i->isVirtual() && SeenVBasesInSecondary.count(Base))
+ continue;
+
+ // Itanium C++ ABI 2.6.2:
+ // Secondary virtual pointers are present for all bases with either
+ // virtual bases or virtual function declarations overridden along a
+ // virtual path.
+ //
+ // If the base class is not dynamic, we don't want to add it, nor any
+ // of its base classes.
+ if (!Base->isDynamicClass())
+ continue;
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
+ bool NonVirtualPrimaryBase;
+ NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
+ bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
+ uint64_t BaseOffset;
+ if (!i->isVirtual()) {
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+ } else
+ BaseOffset = BLayout.getVBaseClassOffset(Base);
+ llvm::Constant *subvtbl = vtbl;
+ const CXXRecordDecl *subVtblClass = VtblClass;
+ if ((Base->getNumVBases() || BaseMorallyVirtual)
+ && !NonVirtualPrimaryBase) {
+ llvm::Constant *init;
+ if (BaseMorallyVirtual || VtblClass == Class)
+ init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
+ else {
+ init = getCtorVtable(BaseSubobject(Base, BaseOffset));
+
+ subvtbl = init;
+ subVtblClass = Base;
+
+ init = BuildVtablePtr(init, Class, Base, BaseOffset);
+ }
+
+ Inits.push_back(init);
+ }
+
+ if (i->isVirtual())
+ SeenVBasesInSecondary.insert(Base);
+
+ Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
+ }
+ }
+
+ /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
+ /// currnet object we're working on.
+ void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
+ // Itanium C++ ABI 2.6.2:
+ // An array of virtual table addresses, called the VTT, is declared for
+ // each class type that has indirect or direct virtual base classes.
+ if (RD->getNumVBases() == 0)
+ return;
+
+ // Remember the sub-VTT index.
+ SubVTTIndicies[RD] = Inits.size();
+
+ llvm::Constant *Vtable;
+ const CXXRecordDecl *VtableClass;
+
+ // First comes the primary virtual table pointer...
+ if (MorallyVirtual) {
+ Vtable = ClassVtbl;
+ VtableClass = Class;
+ } else {
+ Vtable = getCtorVtable(BaseSubobject(RD, Offset));
+ VtableClass = RD;
+ }
+
+ llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset);
+ Inits.push_back(Init);
+
+ // then the secondary VTTs....
+ SecondaryVTTs(RD, Offset, MorallyVirtual);
+
+ // Make sure to clear the set of seen virtual bases.
+ SeenVBasesInSecondary.clear();
+
+ // and last the secondary vtable pointers.
+ Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual);
+ }
+
+ /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
+ /// built from each direct non-virtual proper base that requires a VTT in
+ /// declaration order.
+ void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
+ bool MorallyVirtual=false) {
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ if (i->isVirtual())
+ continue;
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+
+ BuildVTT(Base, BaseOffset, MorallyVirtual);
+ }
+ }
+
+ /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
+ /// graph preorder.
+ void VirtualVTTs(const CXXRecordDecl *RD) {
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ if (i->isVirtual() && !SeenVBase.count(Base)) {
+ SeenVBase.insert(Base);
+ uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
+ BuildVTT(Base, BaseOffset, false);
+ }
+ VirtualVTTs(Base);
+ }
+ }
+
+public:
+ VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
+ CodeGenModule &cgm, bool GenerateDefinition)
+ : Inits(inits), Class(c), CGM(cgm),
+ BLayout(cgm.getContext().getASTRecordLayout(c)),
+ AddressPoints(*cgm.getVtableInfo().AddressPoints[c]),
+ VMContext(cgm.getModule().getContext()),
+ GenerateDefinition(GenerateDefinition) {
+
+ // First comes the primary virtual table pointer for the complete class...
+ ClassVtbl = GenerateDefinition ? CGM.getVtableInfo().getVtable(Class) : 0;
+
+ llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
+ Inits.push_back(Init);
+
+ // then the secondary VTTs...
+ SecondaryVTTs(Class);
+
+ // Make sure to clear the set of seen virtual bases.
+ SeenVBasesInSecondary.clear();
+
+ // then the secondary vtable pointers...
+ Secondary(Class, ClassVtbl, Class);
+
+ // and last, the virtual VTTs.
+ VirtualVTTs(Class);
+ }
+
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
+ return SubVTTIndicies;
+ }
+};
+}
+
+llvm::GlobalVariable *
+CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
+ bool GenerateDefinition,
+ const CXXRecordDecl *RD) {
+ // Only classes that have virtual bases need a VTT.
+ if (RD->getNumVBases() == 0)
+ return 0;
+
+ llvm::SmallString<256> OutName;
+ CGM.getMangleContext().mangleCXXVTT(RD, OutName);
+ llvm::StringRef Name = OutName.str();
+
+ D1(printf("vtt %s\n", RD->getNameAsCString()));
+
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV == 0 || GV->isDeclaration()) {
+ const llvm::Type *Int8PtrTy =
+ llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+
+ std::vector<llvm::Constant *> inits;
+ VTTBuilder b(inits, RD, CGM, GenerateDefinition);
+
+ const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
+ llvm::Constant *Init = 0;
+ if (GenerateDefinition)
+ Init = llvm::ConstantArray::get(Type, inits);
+
+ llvm::GlobalVariable *OldGV = GV;
+ GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
+ Linkage, Init, Name);
+ CGM.setGlobalVisibility(GV, RD);
+
+ if (OldGV) {
+ GV->takeName(OldGV);
+ llvm::Constant *NewPtr =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtr);
+ OldGV->eraseFromParent();
+ }
+ }
+
+ return GV;
+}
+
+CGVtableInfo::CtorVtableInfo
+CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
+ const BaseSubobject &Base) {
+ CtorVtableInfo Info;
+
+ Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
+ /*GenerateDefinition=*/true,
+ RD, Base.getBase(), Base.getBaseOffset(),
+ Info.AddressPoints);
+ return Info;
+}
+
+llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) {
+ return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
+ /*GenerateDefinition=*/false, RD);
+
+}
+
+
+bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // We don't have any virtual bases, just return early.
+ if (!MD->getParent()->getNumVBases())
+ return false;
+
+ // Check if we have a base constructor.
+ if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
+ return true;
+
+ // Check if we have a base destructor.
+ if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
+ return true;
+
+ return false;
+}
+
+uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Base) {
+ ClassPairTy ClassPair(RD, Base);
+
+ SubVTTIndiciesTy::iterator I =
+ SubVTTIndicies.find(ClassPair);
+ if (I != SubVTTIndicies.end())
+ return I->second;
+
+ std::vector<llvm::Constant *> inits;
+ VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
+
+ for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
+ Builder.getSubVTTIndicies().begin(),
+ E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
+ // Insert all indices.
+ ClassPairTy ClassPair(RD, I->first);
+
+ SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
+ }
+
+ I = SubVTTIndicies.find(ClassPair);
+ assert(I != SubVTTIndicies.end() && "Did not find index!");
+
+ return I->second;
+}
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index ae900d6ae70e..e5abfc6f8d57 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -232,8 +232,8 @@ public:
return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
}
-#define D1(x)
-//#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
+//#define D1(x)
+#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
bool updateVBIndex, Index_t current_vbindex) {
@@ -254,7 +254,7 @@ public:
D1(printf(" vbase for %s at %d delta %d most derived %s\n",
Base->getNameAsCString(),
(int)-VCalls.size()-3, (int)BaseOffset,
- Class->getNameAsCString()));
+ MostDerivedClass->getNameAsCString()));
}
// We also record offsets for non-virtual bases to closest enclosing
// virtual base. We do this so that we don't have to search
@@ -376,13 +376,14 @@ public:
CurrentVBaseOffset))
return;
+ D1(printf(" vfn for %s at %d\n",
+ dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
+ (int)Methods.size()));
+
// We didn't find an entry in the vtable that we could use, add a new
// entry.
Methods.AddMethod(GD);
- D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
- (int)Index[GD]));
-
VCallOffset[GD] = Offset/8;
if (MorallyVirtual) {
Index_t &idx = VCall[GD];
@@ -392,7 +393,8 @@ public:
idx = VCalls.size()+1;
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d\n",
- MD->getNameAsString().c_str(), (int)-VCalls.size()-3, 0));
+ dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
+ (int)-VCalls.size()-3, 0));
}
}
}
@@ -429,12 +431,11 @@ public:
continue;
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
- if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
- uint64_t o = Offset + Layout.getBaseClassOffset(Base);
- StartNewTable();
- GenerateVtableForBase(Base, o, MorallyVirtual, false,
- CurrentVBaseOffset, Path);
- }
+ uint64_t o = Offset + Layout.getBaseClassOffset(Base);
+ StartNewTable();
+ GenerateVtableForBase(Base, o, MorallyVirtual, false,
+ true, Base == PrimaryBase && !PrimaryBaseWasVirtual,
+ CurrentVBaseOffset, Path);
}
Path->pop_back();
}
@@ -463,7 +464,7 @@ public:
void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
Index_t AddressPoint) {
D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
- RD->getNameAsCString(), Class->getNameAsCString(),
+ RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
@@ -480,7 +481,7 @@ public:
BLayout.getVBaseClassOffset(RD) != Offset)
break;
D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
- RD->getNameAsCString(), Class->getNameAsCString(),
+ RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
@@ -491,6 +492,7 @@ public:
void FinishGenerateVtable(const CXXRecordDecl *RD,
const ASTRecordLayout &Layout,
const CXXRecordDecl *PrimaryBase,
+ bool ForNPNVBases, bool WasPrimaryBase,
bool PrimaryBaseWasVirtual,
bool MorallyVirtual, int64_t Offset,
bool ForVirtualBase, int64_t CurrentVBaseOffset,
@@ -503,23 +505,27 @@ public:
StartNewTable();
extra = 0;
- bool DeferVCalls = MorallyVirtual || ForVirtualBase;
- int VCallInsertionPoint = VtableComponents.size();
- if (!DeferVCalls) {
- insertVCalls(VCallInsertionPoint);
- } else
- // FIXME: just for extra, or for all uses of VCalls.size post this?
- extra = -VCalls.size();
+ Index_t AddressPoint = 0;
+ int VCallInsertionPoint = 0;
+ if (!ForNPNVBases || !WasPrimaryBase) {
+ bool DeferVCalls = MorallyVirtual || ForVirtualBase;
+ VCallInsertionPoint = VtableComponents.size();
+ if (!DeferVCalls) {
+ insertVCalls(VCallInsertionPoint);
+ } else
+ // FIXME: just for extra, or for all uses of VCalls.size post this?
+ extra = -VCalls.size();
- // Add the offset to top.
- VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
+ // Add the offset to top.
+ VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
- // Add the RTTI information.
- VtableComponents.push_back(rtti);
+ // Add the RTTI information.
+ VtableComponents.push_back(rtti);
- Index_t AddressPoint = VtableComponents.size();
+ AddressPoint = VtableComponents.size();
- AppendMethodsToVtable();
+ AppendMethodsToVtable();
+ }
// and then the non-virtual bases.
NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
@@ -537,7 +543,8 @@ public:
insertVCalls(VCallInsertionPoint);
}
- AddAddressPoints(RD, Offset, AddressPoint);
+ if (!ForNPNVBases || !WasPrimaryBase)
+ AddAddressPoints(RD, Offset, AddressPoint);
if (alloc) {
delete Path;
@@ -557,13 +564,13 @@ public:
// vtables are composed from the chain of primaries.
if (PrimaryBase && !PrimaryBaseWasVirtual) {
D1(printf(" doing primaries for %s most derived %s\n",
- RD->getNameAsCString(), Class->getNameAsCString()));
+ RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
updateVBIndex, current_vbindex, CurrentVBaseOffset);
}
D1(printf(" doing vcall entries for %s most derived %s\n",
- RD->getNameAsCString(), Class->getNameAsCString()));
+ RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
// And add the virtuals for the class to the primary vtable.
AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset);
@@ -589,7 +596,7 @@ public:
}
D1(printf(" doing primaries for %s most derived %s\n",
- RD->getNameAsCString(), Class->getNameAsCString()));
+ RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
@@ -597,7 +604,7 @@ public:
}
D1(printf(" doing vbase entries for %s most derived %s\n",
- RD->getNameAsCString(), Class->getNameAsCString()));
+ RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
if (RDisVirtualBase || bottom) {
@@ -609,6 +616,8 @@ public:
void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
bool MorallyVirtual = false,
bool ForVirtualBase = false,
+ bool ForNPNVBases = false,
+ bool WasPrimaryBase = true,
int CurrentVBaseOffset = 0,
Path_t *Path = 0) {
if (!RD->isDynamicClass())
@@ -626,20 +635,22 @@ public:
extra = 0;
D1(printf("building entries for base %s most derived %s\n",
- RD->getNameAsCString(), Class->getNameAsCString()));
+ RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
if (ForVirtualBase)
extra = VCalls.size();
- VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
- CurrentVBaseOffset, true);
+ if (!ForNPNVBases || !WasPrimaryBase) {
+ VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0,
+ ForVirtualBase, CurrentVBaseOffset, true);
- if (Path)
- OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
+ if (Path)
+ OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
+ }
- FinishGenerateVtable(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
- MorallyVirtual, Offset, ForVirtualBase,
- CurrentVBaseOffset, Path);
+ FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase,
+ PrimaryBaseWasVirtual, MorallyVirtual, Offset,
+ ForVirtualBase, CurrentVBaseOffset, Path);
}
void GenerateVtableForVBases(const CXXRecordDecl *RD,
@@ -665,9 +676,9 @@ public:
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
int64_t CurrentVBaseOffset = BaseOffset;
D1(printf("vtable %s virtual base %s\n",
- Class->getNameAsCString(), Base->getNameAsCString()));
- GenerateVtableForBase(Base, BaseOffset, true, true, CurrentVBaseOffset,
- Path);
+ MostDerivedClass->getNameAsCString(), Base->getNameAsCString()));
+ GenerateVtableForBase(Base, BaseOffset, true, true, false,
+ true, CurrentVBaseOffset, Path);
}
int64_t BaseOffset;
if (i->isVirtual())
@@ -823,14 +834,14 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
MD->getNameAsString().c_str(), (int)-idx-3,
- (int)VCalls[idx-1], Class->getNameAsCString()));
+ (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
} else {
NonVirtualOffset[GD] = NonVirtualOffset[OGD];
VCallOffset[GD] = VCallOffset[OGD];
VCalls[idx-1] = -VCallOffset[OGD] + OverrideOffset/8;
D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
MD->getNameAsString().c_str(), (int)-idx-3,
- (int)VCalls[idx-1], Class->getNameAsCString()));
+ (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
}
int64_t NonVirtualAdjustment = NonVirtualOffset[GD];
int64_t VirtualAdjustment =
@@ -1205,284 +1216,6 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
return GV;
}
-namespace {
-class VTTBuilder {
- /// Inits - The list of values built for the VTT.
- std::vector<llvm::Constant *> &Inits;
- /// Class - The most derived class that this vtable is being built for.
- const CXXRecordDecl *Class;
- CodeGenModule &CGM; // Per-module state.
- llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
- /// BLayout - Layout for the most derived class that this vtable is being
- /// built for.
- const ASTRecordLayout &BLayout;
- CGVtableInfo::AddrMap_t &AddressPoints;
- // vtbl - A pointer to the vtable for Class.
- llvm::Constant *ClassVtbl;
- llvm::LLVMContext &VMContext;
-
- llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
-
- bool GenerateDefinition;
-
- llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
- llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
- CtorVtableAddressPoints;
-
- llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
- if (!GenerateDefinition)
- return 0;
-
- llvm::Constant *&CtorVtable = CtorVtables[Base];
- if (!CtorVtable) {
- // Build the vtable.
- CGVtableInfo::CtorVtableInfo Info
- = CGM.getVtableInfo().getCtorVtable(Class, Base);
-
- CtorVtable = Info.Vtable;
-
- // Add the address points for this base.
- for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
- Info.AddressPoints.begin(), E = Info.AddressPoints.end();
- I != E; ++I) {
- uint64_t &AddressPoint =
- CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)];
-
- // Check if we already have the address points for this base.
- if (AddressPoint)
- break;
-
- // Otherwise, insert it.
- AddressPoint = I->second;
- }
- }
-
- return CtorVtable;
- }
-
-
- /// BuildVtablePtr - Build up a referene to the given secondary vtable
- llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
- const CXXRecordDecl *VtableClass,
- const CXXRecordDecl *RD,
- uint64_t Offset) {
- int64_t AddressPoint =
- (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
-
- // FIXME: We can never have 0 address point. Do this for now so gepping
- // retains the same structure. Later we'll just assert.
- if (AddressPoint == 0)
- AddressPoint = 1;
- D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
- RD->getNameAsCString(), VtblClass->getNameAsCString(),
- Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
-
- llvm::Value *Idxs[] = {
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
- };
-
- llvm::Constant *Init =
- llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
-
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
- return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
- }
-
- /// Secondary - Add the secondary vtable pointers to Inits. Offset is the
- /// current offset in bits to the object we're working on.
- void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
- const CXXRecordDecl *VtblClass, uint64_t Offset=0,
- bool MorallyVirtual=false) {
- if (RD->getNumVBases() == 0 && ! MorallyVirtual)
- return;
-
- for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
- e = RD->bases_end(); i != e; ++i) {
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
- const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
- const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
- bool NonVirtualPrimaryBase;
- NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
- bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
- uint64_t BaseOffset;
- if (!i->isVirtual()) {
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
- BaseOffset = Offset + Layout.getBaseClassOffset(Base);
- } else
- BaseOffset = BLayout.getVBaseClassOffset(Base);
- llvm::Constant *subvtbl = vtbl;
- const CXXRecordDecl *subVtblClass = VtblClass;
- if ((Base->getNumVBases() || BaseMorallyVirtual)
- && !NonVirtualPrimaryBase) {
- // FIXME: Slightly too many of these for __ZTT8test8_B2
- llvm::Constant *init;
- if (BaseMorallyVirtual)
- init = GenerateDefinition ?
- BuildVtablePtr(vtbl, VtblClass, RD, Offset) : 0;
- else {
- init = GenerateDefinition ?
- getCtorVtable(BaseSubobject(Base, BaseOffset)) : 0;
-
- subvtbl = init;
- subVtblClass = Base;
-
- init = GenerateDefinition ?
- BuildVtablePtr(init, Class, Base, BaseOffset) : 0;
- }
- Inits.push_back(init);
- }
- Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
- }
- }
-
- /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
- /// currnet object we're working on.
- void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
- if (RD->getNumVBases() == 0 && !MorallyVirtual)
- return;
-
- llvm::Constant *Vtable;
- const CXXRecordDecl *VtableClass;
-
- // First comes the primary virtual table pointer...
- if (MorallyVirtual) {
- Vtable = GenerateDefinition ? ClassVtbl : 0;
- VtableClass = Class;
- } else {
- Vtable = GenerateDefinition ?
- getCtorVtable(BaseSubobject(RD, Offset)) : 0;
- VtableClass = RD;
- }
-
- llvm::Constant *Init = GenerateDefinition ?
- BuildVtablePtr(Vtable, VtableClass, RD, Offset) : 0;
- Inits.push_back(Init);
-
- // then the secondary VTTs....
- SecondaryVTTs(RD, Offset, MorallyVirtual);
-
- // and last the secondary vtable pointers.
- Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual);
- }
-
- /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
- /// built from each direct non-virtual proper base that requires a VTT in
- /// declaration order.
- void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
- bool MorallyVirtual=false) {
- for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
- e = RD->bases_end(); i != e; ++i) {
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
- if (i->isVirtual())
- continue;
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
- uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
-
- // Remember the sub-VTT index.
- SubVTTIndicies[Base] = Inits.size();
-
- BuildVTT(Base, BaseOffset, MorallyVirtual);
- }
- }
-
- /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
- /// graph preorder.
- void VirtualVTTs(const CXXRecordDecl *RD) {
- for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
- e = RD->bases_end(); i != e; ++i) {
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
- if (i->isVirtual() && !SeenVBase.count(Base)) {
- // Remember the sub-VTT index.
- SubVTTIndicies[Base] = Inits.size();
-
- SeenVBase.insert(Base);
- uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
- BuildVTT(Base, BaseOffset, true);
- }
- VirtualVTTs(Base);
- }
- }
-
-public:
- VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
- CodeGenModule &cgm, bool GenerateDefinition)
- : Inits(inits), Class(c), CGM(cgm),
- BLayout(cgm.getContext().getASTRecordLayout(c)),
- AddressPoints(*cgm.getVtableInfo().AddressPoints[c]),
- VMContext(cgm.getModule().getContext()),
- GenerateDefinition(GenerateDefinition) {
-
- // First comes the primary virtual table pointer for the complete class...
- ClassVtbl = CGM.getVtableInfo().getVtable(Class);
- llvm::Constant *Init = GenerateDefinition ?
- BuildVtablePtr(ClassVtbl, Class, Class, 0) : 0;
- Inits.push_back(Init);
-
- // then the secondary VTTs...
- SecondaryVTTs(Class);
-
- // then the secondary vtable pointers...
- Secondary(Class, ClassVtbl, Class);
-
- // and last, the virtual VTTs.
- VirtualVTTs(Class);
- }
-
- llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
- return SubVTTIndicies;
- }
-};
-}
-
-llvm::GlobalVariable *
-CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
- bool GenerateDefinition,
- const CXXRecordDecl *RD) {
- // Only classes that have virtual bases need a VTT.
- if (RD->getNumVBases() == 0)
- return 0;
-
- llvm::SmallString<256> OutName;
- CGM.getMangleContext().mangleCXXVTT(RD, OutName);
- llvm::StringRef Name = OutName.str();
-
- D1(printf("vtt %s\n", RD->getNameAsCString()));
-
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
- if (GV == 0 || GV->isDeclaration()) {
- const llvm::Type *Int8PtrTy =
- llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
-
- std::vector<llvm::Constant *> inits;
- VTTBuilder b(inits, RD, CGM, GenerateDefinition);
-
- const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
- llvm::Constant *Init = 0;
- if (GenerateDefinition)
- Init = llvm::ConstantArray::get(Type, inits);
-
- llvm::GlobalVariable *OldGV = GV;
- GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
- Linkage, Init, Name);
- CGM.setGlobalVisibility(GV, RD);
-
- if (OldGV) {
- GV->takeName(OldGV);
- llvm::Constant *NewPtr =
- llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
- OldGV->replaceAllUsesWith(NewPtr);
- OldGV->eraseFromParent();
- }
- }
-
- return GV;
-}
-
void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
const CXXRecordDecl *RD) {
llvm::GlobalVariable *&Vtable = Vtables[RD];
@@ -1510,25 +1243,6 @@ llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
return Vtable;
}
-CGVtableInfo::CtorVtableInfo
-CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
- const BaseSubobject &Base) {
- CtorVtableInfo Info;
-
- Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
- /*GenerateDefinition=*/true,
- RD, Base.getBase(), Base.getBaseOffset(),
- Info.AddressPoints);
- return Info;
-}
-
-llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) {
- return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
- /*GenerateDefinition=*/false, RD);
-
-}
-
-
void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const CXXRecordDecl *RD = MD->getParent();
@@ -1562,47 +1276,3 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
}
}
-bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) {
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-
- // We don't have any virtual bases, just return early.
- if (!MD->getParent()->getNumVBases())
- return false;
-
- // Check if we have a base constructor.
- if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
- return true;
-
- // Check if we have a base destructor.
- if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
- return true;
-
- return false;
-}
-
-uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD,
- const CXXRecordDecl *Base) {
- ClassPairTy ClassPair(RD, Base);
-
- SubVTTIndiciesTy::iterator I =
- SubVTTIndicies.find(ClassPair);
- if (I != SubVTTIndicies.end())
- return I->second;
-
- std::vector<llvm::Constant *> inits;
- VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
-
- for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
- Builder.getSubVTTIndicies().begin(),
- E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
- // Insert all indices.
- ClassPairTy ClassPair(RD, I->first);
-
- SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
- }
-
- I = SubVTTIndicies.find(ClassPair);
- assert(I != SubVTTIndicies.end() && "Did not find index!");
-
- return I->second;
-}
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 45469d39e4af..e72a1d9e0946 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -24,6 +24,7 @@ add_clang_library(clangCodeGen
CGStmt.cpp
CGTemporaries.cpp
CGVtable.cpp
+ CGVTT.cpp
CodeGenFunction.cpp
CodeGenModule.cpp
CodeGenTypes.cpp
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5ecc30eb4ea2..cf504a7c2a0c 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -67,6 +67,15 @@ CodeGenModule::~CodeGenModule() {
delete DebugInfo;
}
+void CodeGenModule::createObjCRuntime() {
+ if (!Features.NeXTRuntime)
+ Runtime = CreateGNUObjCRuntime(*this);
+ else if (Features.ObjCNonFragileABI)
+ Runtime = CreateMacNonFragileABIObjCRuntime(*this);
+ else
+ Runtime = CreateMacObjCRuntime(*this);
+}
+
void CodeGenModule::Release() {
EmitDeferred();
EmitCXXGlobalInitFunc();
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index c7aa7a47a836..81f39791fcd0 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -161,6 +161,9 @@ class CodeGenModule : public BlockModule {
/// strings. This value has type int * but is actually an Obj-C class pointer.
llvm::Constant *CFConstantStringClassRef;
+ /// Lazily create the Objective-C runtime
+ void createObjCRuntime();
+
llvm::LLVMContext &VMContext;
public:
CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
@@ -174,7 +177,7 @@ public:
/// getObjCRuntime() - Return a reference to the configured
/// Objective-C runtime.
CGObjCRuntime &getObjCRuntime() {
- assert(Runtime && "No Objective-C runtime has been configured.");
+ if (!Runtime) createObjCRuntime();
return *Runtime;
}
diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp
deleted file mode 100644
index 863a297cc6a5..000000000000
--- a/lib/CodeGen/TargetABIInfo.cpp
+++ /dev/null
@@ -1,1821 +0,0 @@
-//===---- TargetABIInfo.cpp - Encapsulate target ABI details ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These classes wrap the information about a call or function
-// definition used to handle ABI compliancy.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ABIInfo.h"
-#include "CodeGenFunction.h"
-#include "clang/AST/RecordLayout.h"
-#include "llvm/Type.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace clang;
-using namespace CodeGen;
-
-ABIInfo::~ABIInfo() {}
-
-void ABIArgInfo::dump() const {
- llvm::raw_ostream &OS = llvm::errs();
- OS << "(ABIArgInfo Kind=";
- switch (TheKind) {
- case Direct:
- OS << "Direct";
- break;
- case Extend:
- OS << "Extend";
- break;
- case Ignore:
- OS << "Ignore";
- break;
- case Coerce:
- OS << "Coerce Type=";
- getCoerceToType()->print(OS);
- break;
- case Indirect:
- OS << "Indirect Align=" << getIndirectAlign();
- break;
- case Expand:
- OS << "Expand";
- break;
- }
- OS << ")\n";
-}
-
-static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
-
-/// isEmptyField - Return true iff a the field is "empty", that is it
-/// is an unnamed bit-field or an (array of) empty record(s).
-static bool isEmptyField(ASTContext &Context, const FieldDecl *FD,
- bool AllowArrays) {
- if (FD->isUnnamedBitfield())
- return true;
-
- QualType FT = FD->getType();
-
- // Constant arrays of empty records count as empty, strip them off.
- if (AllowArrays)
- while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT))
- FT = AT->getElementType();
-
- return isEmptyRecord(Context, FT, AllowArrays);
-}
-
-/// isEmptyRecord - Return true iff a structure contains only empty
-/// fields. Note that a structure with a flexible array member is not
-/// considered empty.
-static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
- const RecordType *RT = T->getAs<RecordType>();
- if (!RT)
- return 0;
- const RecordDecl *RD = RT->getDecl();
- if (RD->hasFlexibleArrayMember())
- return false;
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i)
- if (!isEmptyField(Context, *i, AllowArrays))
- return false;
- return true;
-}
-
-/// hasNonTrivialDestructorOrCopyConstructor - Determine if a type has either
-/// a non-trivial destructor or a non-trivial copy constructor.
-static bool hasNonTrivialDestructorOrCopyConstructor(const RecordType *RT) {
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return false;
-
- return !RD->hasTrivialDestructor() || !RD->hasTrivialCopyConstructor();
-}
-
-/// isRecordWithNonTrivialDestructorOrCopyConstructor - Determine if a type is
-/// a record type with either a non-trivial destructor or a non-trivial copy
-/// constructor.
-static bool isRecordWithNonTrivialDestructorOrCopyConstructor(QualType T) {
- const RecordType *RT = T->getAs<RecordType>();
- if (!RT)
- return false;
-
- return hasNonTrivialDestructorOrCopyConstructor(RT);
-}
-
-/// isSingleElementStruct - Determine if a structure is a "single
-/// element struct", i.e. it has exactly one non-empty field or
-/// exactly one field which is itself a single element
-/// struct. Structures with flexible array members are never
-/// considered single element structs.
-///
-/// \return The field declaration for the single non-empty field, if
-/// it exists.
-static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
- const RecordType *RT = T->getAsStructureType();
- if (!RT)
- return 0;
-
- const RecordDecl *RD = RT->getDecl();
- if (RD->hasFlexibleArrayMember())
- return 0;
-
- const Type *Found = 0;
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- const FieldDecl *FD = *i;
- QualType FT = FD->getType();
-
- // Ignore empty fields.
- if (isEmptyField(Context, FD, true))
- continue;
-
- // If we already found an element then this isn't a single-element
- // struct.
- if (Found)
- return 0;
-
- // Treat single element arrays as the element.
- while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
- if (AT->getSize().getZExtValue() != 1)
- break;
- FT = AT->getElementType();
- }
-
- if (!CodeGenFunction::hasAggregateLLVMType(FT)) {
- Found = FT.getTypePtr();
- } else {
- Found = isSingleElementStruct(FT, Context);
- if (!Found)
- return 0;
- }
- }
-
- return Found;
-}
-
-static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) {
- if (!Ty->getAs<BuiltinType>() && !Ty->isAnyPointerType() &&
- !Ty->isAnyComplexType() && !Ty->isEnumeralType() &&
- !Ty->isBlockPointerType())
- return false;
-
- uint64_t Size = Context.getTypeSize(Ty);
- return Size == 32 || Size == 64;
-}
-
-/// canExpandIndirectArgument - Test whether an argument type which is to be
-/// passed indirectly (on the stack) would have the equivalent layout if it was
-/// expanded into separate arguments. If so, we prefer to do the latter to avoid
-/// inhibiting optimizations.
-///
-// FIXME: This predicate is missing many cases, currently it just follows
-// llvm-gcc (checks that all fields are 32-bit or 64-bit primitive types). We
-// should probably make this smarter, or better yet make the LLVM backend
-// capable of handling it.
-static bool canExpandIndirectArgument(QualType Ty, ASTContext &Context) {
- // We can only expand structure types.
- const RecordType *RT = Ty->getAs<RecordType>();
- if (!RT)
- return false;
-
- // We can only expand (C) structures.
- //
- // FIXME: This needs to be generalized to handle classes as well.
- const RecordDecl *RD = RT->getDecl();
- if (!RD->isStruct() || isa<CXXRecordDecl>(RD))
- return false;
-
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- const FieldDecl *FD = *i;
-
- if (!is32Or64BitBasicType(FD->getType(), Context))
- return false;
-
- // FIXME: Reject bit-fields wholesale; there are two problems, we don't know
- // how to expand them yet, and the predicate for telling if a bitfield still
- // counts as "basic" is more complicated than what we were doing previously.
- if (FD->isBitField())
- return false;
- }
-
- return true;
-}
-
-static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) {
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- const FieldDecl *FD = *i;
-
- if (FD->getType()->isVectorType() &&
- Context.getTypeSize(FD->getType()) >= 128)
- return true;
-
- if (const RecordType* RT = FD->getType()->getAs<RecordType>())
- if (typeContainsSSEVector(RT->getDecl(), Context))
- return true;
- }
-
- return false;
-}
-
-namespace {
-/// DefaultABIInfo - The default implementation for ABI specific
-/// details. This implementation provides information which results in
-/// self-consistent and sensible LLVM IR generation, but does not
-/// conform to any particular ABI.
-class DefaultABIInfo : public ABIInfo {
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
- }
-
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
-};
-
-/// X86_32ABIInfo - The X86-32 ABI information.
-class X86_32ABIInfo : public ABIInfo {
- ASTContext &Context;
- bool IsDarwinVectorABI;
- bool IsSmallStructInRegABI;
-
- static bool isRegisterSize(unsigned Size) {
- return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
- }
-
- static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context);
-
- static unsigned getIndirectArgumentAlignment(QualType Ty,
- ASTContext &Context);
-
-public:
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
- }
-
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
-
- X86_32ABIInfo(ASTContext &Context, bool d, bool p)
- : ABIInfo(), Context(Context), IsDarwinVectorABI(d),
- IsSmallStructInRegABI(p) {}
-};
-}
-
-
-/// shouldReturnTypeInRegister - Determine if the given type should be
-/// passed in a register (for the Darwin ABI).
-bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
- ASTContext &Context) {
- uint64_t Size = Context.getTypeSize(Ty);
-
- // Type must be register sized.
- if (!isRegisterSize(Size))
- return false;
-
- if (Ty->isVectorType()) {
- // 64- and 128- bit vectors inside structures are not returned in
- // registers.
- if (Size == 64 || Size == 128)
- return false;
-
- return true;
- }
-
- // If this is a builtin, pointer, enum, or complex type, it is ok.
- if (Ty->getAs<BuiltinType>() || Ty->isAnyPointerType() ||
- Ty->isAnyComplexType() || Ty->isEnumeralType() ||
- Ty->isBlockPointerType())
- return true;
-
- // Arrays are treated like records.
- if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty))
- return shouldReturnTypeInRegister(AT->getElementType(), Context);
-
- // Otherwise, it must be a record type.
- const RecordType *RT = Ty->getAs<RecordType>();
- if (!RT) return false;
-
- // Structure types are passed in register if all fields would be
- // passed in a register.
- for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(),
- e = RT->getDecl()->field_end(); i != e; ++i) {
- const FieldDecl *FD = *i;
-
- // Empty fields are ignored.
- if (isEmptyField(Context, FD, true))
- continue;
-
- // Check fields recursively.
- if (!shouldReturnTypeInRegister(FD->getType(), Context))
- return false;
- }
-
- return true;
-}
-
-ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType()) {
- return ABIArgInfo::getIgnore();
- } else if (const VectorType *VT = RetTy->getAs<VectorType>()) {
- // On Darwin, some vectors are returned in registers.
- if (IsDarwinVectorABI) {
- uint64_t Size = Context.getTypeSize(RetTy);
-
- // 128-bit vectors are a special case; they are returned in
- // registers and we need to make sure to pick a type the LLVM
- // backend will like.
- if (Size == 128)
- return ABIArgInfo::getCoerce(llvm::VectorType::get(
- llvm::Type::getInt64Ty(VMContext), 2));
-
- // Always return in register if it fits in a general purpose
- // register, or if it is 64 bits and has a single element.
- if ((Size == 8 || Size == 16 || Size == 32) ||
- (Size == 64 && VT->getNumElements() == 1))
- return ABIArgInfo::getCoerce(llvm::IntegerType::get(VMContext, Size));
-
- return ABIArgInfo::getIndirect(0);
- }
-
- return ABIArgInfo::getDirect();
- } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
- if (const RecordType *RT = RetTy->getAsStructureType()) {
- // Structures with either a non-trivial destructor or a non-trivial
- // copy constructor are always indirect.
- if (hasNonTrivialDestructorOrCopyConstructor(RT))
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
-
- // Structures with flexible arrays are always indirect.
- if (RT->getDecl()->hasFlexibleArrayMember())
- return ABIArgInfo::getIndirect(0);
- }
-
- // If specified, structs and unions are always indirect.
- if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
- return ABIArgInfo::getIndirect(0);
-
- // Classify "single element" structs as their element type.
- if (const Type *SeltTy = isSingleElementStruct(RetTy, Context)) {
- if (const BuiltinType *BT = SeltTy->getAs<BuiltinType>()) {
- if (BT->isIntegerType()) {
- // We need to use the size of the structure, padding
- // bit-fields can adjust that to be larger than the single
- // element type.
- uint64_t Size = Context.getTypeSize(RetTy);
- return ABIArgInfo::getCoerce(
- llvm::IntegerType::get(VMContext, (unsigned) Size));
- } else if (BT->getKind() == BuiltinType::Float) {
- assert(Context.getTypeSize(RetTy) == Context.getTypeSize(SeltTy) &&
- "Unexpect single element structure size!");
- return ABIArgInfo::getCoerce(llvm::Type::getFloatTy(VMContext));
- } else if (BT->getKind() == BuiltinType::Double) {
- assert(Context.getTypeSize(RetTy) == Context.getTypeSize(SeltTy) &&
- "Unexpect single element structure size!");
- return ABIArgInfo::getCoerce(llvm::Type::getDoubleTy(VMContext));
- }
- } else if (SeltTy->isPointerType()) {
- // FIXME: It would be really nice if this could come out as the proper
- // pointer type.
- const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
- return ABIArgInfo::getCoerce(PtrTy);
- } else if (SeltTy->isVectorType()) {
- // 64- and 128-bit vectors are never returned in a
- // register when inside a structure.
- uint64_t Size = Context.getTypeSize(RetTy);
- if (Size == 64 || Size == 128)
- return ABIArgInfo::getIndirect(0);
-
- return classifyReturnType(QualType(SeltTy, 0), Context, VMContext);
- }
- }
-
- // Small structures which are register sized are generally returned
- // in a register.
- if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, Context)) {
- uint64_t Size = Context.getTypeSize(RetTy);
- return ABIArgInfo::getCoerce(llvm::IntegerType::get(VMContext, Size));
- }
-
- return ABIArgInfo::getIndirect(0);
- } else {
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
-}
-
-unsigned X86_32ABIInfo::getIndirectArgumentAlignment(QualType Ty,
- ASTContext &Context) {
- unsigned Align = Context.getTypeAlign(Ty);
- if (Align < 128) return 0;
- if (const RecordType* RT = Ty->getAs<RecordType>())
- if (typeContainsSSEVector(RT->getDecl(), Context))
- return 16;
- return 0;
-}
-
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- // FIXME: Set alignment on indirect arguments.
- if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
- // Structures with flexible arrays are always indirect.
- if (const RecordType *RT = Ty->getAsStructureType())
- if (RT->getDecl()->hasFlexibleArrayMember())
- return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty,
- Context));
-
- // Ignore empty structs.
- if (Ty->isStructureType() && Context.getTypeSize(Ty) == 0)
- return ABIArgInfo::getIgnore();
-
- // Expand small (<= 128-bit) record types when we know that the stack layout
- // of those arguments will match the struct. This is important because the
- // LLVM backend isn't smart enough to remove byval, which inhibits many
- // optimizations.
- if (Context.getTypeSize(Ty) <= 4*32 &&
- canExpandIndirectArgument(Ty, Context))
- return ABIArgInfo::getExpand();
-
- return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context));
- } else {
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
-}
-
-llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
- const llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
-
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
- "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
- llvm::Type *PTy =
- llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
-
- uint64_t Offset =
- llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);
- llvm::Value *NextAddr =
- Builder.CreateGEP(Addr, llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(CGF.getLLVMContext()), Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
-
- return AddrTyped;
-}
-
-namespace {
-/// X86_64ABIInfo - The X86_64 ABI information.
-class X86_64ABIInfo : public ABIInfo {
- enum Class {
- Integer = 0,
- SSE,
- SSEUp,
- X87,
- X87Up,
- ComplexX87,
- NoClass,
- Memory
- };
-
- /// merge - Implement the X86_64 ABI merging algorithm.
- ///
- /// Merge an accumulating classification \arg Accum with a field
- /// classification \arg Field.
- ///
- /// \param Accum - The accumulating classification. This should
- /// always be either NoClass or the result of a previous merge
- /// call. In addition, this should never be Memory (the caller
- /// should just return Memory for the aggregate).
- Class merge(Class Accum, Class Field) const;
-
- /// classify - Determine the x86_64 register classes in which the
- /// given type T should be passed.
- ///
- /// \param Lo - The classification for the parts of the type
- /// residing in the low word of the containing object.
- ///
- /// \param Hi - The classification for the parts of the type
- /// residing in the high word of the containing object.
- ///
- /// \param OffsetBase - The bit offset of this type in the
- /// containing object. Some parameters are classified different
- /// depending on whether they straddle an eightbyte boundary.
- ///
- /// If a word is unused its result will be NoClass; if a type should
- /// be passed in Memory then at least the classification of \arg Lo
- /// will be Memory.
- ///
- /// The \arg Lo class will be NoClass iff the argument is ignored.
- ///
- /// If the \arg Lo class is ComplexX87, then the \arg Hi class will
- /// also be ComplexX87.
- void classify(QualType T, ASTContext &Context, uint64_t OffsetBase,
- Class &Lo, Class &Hi) const;
-
- /// getCoerceResult - Given a source type \arg Ty and an LLVM type
- /// to coerce to, chose the best way to pass Ty in the same place
- /// that \arg CoerceTo would be passed, but while keeping the
- /// emitted code as simple as possible.
- ///
- /// FIXME: Note, this should be cleaned up to just take an enumeration of all
- /// the ways we might want to pass things, instead of constructing an LLVM
- /// type. This makes this code more explicit, and it makes it clearer that we
- /// are also doing this for correctness in the case of passing scalar types.
- ABIArgInfo getCoerceResult(QualType Ty,
- const llvm::Type *CoerceTo,
- ASTContext &Context) const;
-
- /// getIndirectResult - Give a source type \arg Ty, return a suitable result
- /// such that the argument will be passed in memory.
- ABIArgInfo getIndirectResult(QualType Ty,
- ASTContext &Context) const;
-
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext,
- unsigned &neededInt,
- unsigned &neededSSE) const;
-
-public:
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
-};
-}
-
-X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum,
- Class Field) const {
- // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is
- // classified recursively so that always two fields are
- // considered. The resulting class is calculated according to
- // the classes of the fields in the eightbyte:
- //
- // (a) If both classes are equal, this is the resulting class.
- //
- // (b) If one of the classes is NO_CLASS, the resulting class is
- // the other class.
- //
- // (c) If one of the classes is MEMORY, the result is the MEMORY
- // class.
- //
- // (d) If one of the classes is INTEGER, the result is the
- // INTEGER.
- //
- // (e) If one of the classes is X87, X87UP, COMPLEX_X87 class,
- // MEMORY is used as class.
- //
- // (f) Otherwise class SSE is used.
-
- // Accum should never be memory (we should have returned) or
- // ComplexX87 (because this cannot be passed in a structure).
- assert((Accum != Memory && Accum != ComplexX87) &&
- "Invalid accumulated classification during merge.");
- if (Accum == Field || Field == NoClass)
- return Accum;
- else if (Field == Memory)
- return Memory;
- else if (Accum == NoClass)
- return Field;
- else if (Accum == Integer || Field == Integer)
- return Integer;
- else if (Field == X87 || Field == X87Up || Field == ComplexX87 ||
- Accum == X87 || Accum == X87Up)
- return Memory;
- else
- return SSE;
-}
-
-void X86_64ABIInfo::classify(QualType Ty,
- ASTContext &Context,
- uint64_t OffsetBase,
- Class &Lo, Class &Hi) const {
- // FIXME: This code can be simplified by introducing a simple value class for
- // Class pairs with appropriate constructor methods for the various
- // situations.
-
- // FIXME: Some of the split computations are wrong; unaligned vectors
- // shouldn't be passed in registers for example, so there is no chance they
- // can straddle an eightbyte. Verify & simplify.
-
- Lo = Hi = NoClass;
-
- Class &Current = OffsetBase < 64 ? Lo : Hi;
- Current = Memory;
-
- if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
- BuiltinType::Kind k = BT->getKind();
-
- if (k == BuiltinType::Void) {
- Current = NoClass;
- } else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
- Lo = Integer;
- Hi = Integer;
- } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
- Current = Integer;
- } else if (k == BuiltinType::Float || k == BuiltinType::Double) {
- Current = SSE;
- } else if (k == BuiltinType::LongDouble) {
- Lo = X87;
- Hi = X87Up;
- }
- // FIXME: _Decimal32 and _Decimal64 are SSE.
- // FIXME: _float128 and _Decimal128 are (SSE, SSEUp).
- } else if (const EnumType *ET = Ty->getAs<EnumType>()) {
- // Classify the underlying integer type.
- classify(ET->getDecl()->getIntegerType(), Context, OffsetBase, Lo, Hi);
- } else if (Ty->hasPointerRepresentation()) {
- Current = Integer;
- } else if (const VectorType *VT = Ty->getAs<VectorType>()) {
- uint64_t Size = Context.getTypeSize(VT);
- if (Size == 32) {
- // gcc passes all <4 x char>, <2 x short>, <1 x int>, <1 x
- // float> as integer.
- Current = Integer;
-
- // If this type crosses an eightbyte boundary, it should be
- // split.
- uint64_t EB_Real = (OffsetBase) / 64;
- uint64_t EB_Imag = (OffsetBase + Size - 1) / 64;
- if (EB_Real != EB_Imag)
- Hi = Lo;
- } else if (Size == 64) {
- // gcc passes <1 x double> in memory. :(
- if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::Double))
- return;
-
- // gcc passes <1 x long long> as INTEGER.
- if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::LongLong))
- Current = Integer;
- else
- Current = SSE;
-
- // If this type crosses an eightbyte boundary, it should be
- // split.
- if (OffsetBase && OffsetBase != 64)
- Hi = Lo;
- } else if (Size == 128) {
- Lo = SSE;
- Hi = SSEUp;
- }
- } else if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
- QualType ET = Context.getCanonicalType(CT->getElementType());
-
- uint64_t Size = Context.getTypeSize(Ty);
- if (ET->isIntegralType()) {
- if (Size <= 64)
- Current = Integer;
- else if (Size <= 128)
- Lo = Hi = Integer;
- } else if (ET == Context.FloatTy)
- Current = SSE;
- else if (ET == Context.DoubleTy)
- Lo = Hi = SSE;
- else if (ET == Context.LongDoubleTy)
- Current = ComplexX87;
-
- // If this complex type crosses an eightbyte boundary then it
- // should be split.
- uint64_t EB_Real = (OffsetBase) / 64;
- uint64_t EB_Imag = (OffsetBase + Context.getTypeSize(ET)) / 64;
- if (Hi == NoClass && EB_Real != EB_Imag)
- Hi = Lo;
- } else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
- // Arrays are treated like structures.
-
- uint64_t Size = Context.getTypeSize(Ty);
-
- // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
- // than two eightbytes, ..., it has class MEMORY.
- if (Size > 128)
- return;
-
- // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
- // fields, it has class MEMORY.
- //
- // Only need to check alignment of array base.
- if (OffsetBase % Context.getTypeAlign(AT->getElementType()))
- return;
-
- // Otherwise implement simplified merge. We could be smarter about
- // this, but it isn't worth it and would be harder to verify.
- Current = NoClass;
- uint64_t EltSize = Context.getTypeSize(AT->getElementType());
- uint64_t ArraySize = AT->getSize().getZExtValue();
- for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
- Class FieldLo, FieldHi;
- classify(AT->getElementType(), Context, Offset, FieldLo, FieldHi);
- Lo = merge(Lo, FieldLo);
- Hi = merge(Hi, FieldHi);
- if (Lo == Memory || Hi == Memory)
- break;
- }
-
- // Do post merger cleanup (see below). Only case we worry about is Memory.
- if (Hi == Memory)
- Lo = Memory;
- assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp array classification.");
- } else if (const RecordType *RT = Ty->getAs<RecordType>()) {
- uint64_t Size = Context.getTypeSize(Ty);
-
- // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
- // than two eightbytes, ..., it has class MEMORY.
- if (Size > 128)
- return;
-
- // AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial
- // copy constructor or a non-trivial destructor, it is passed by invisible
- // reference.
- if (hasNonTrivialDestructorOrCopyConstructor(RT))
- return;
-
- const RecordDecl *RD = RT->getDecl();
-
- // Assume variable sized types are passed in memory.
- if (RD->hasFlexibleArrayMember())
- return;
-
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
- // Reset Lo class, this will be recomputed.
- Current = NoClass;
-
- // If this is a C++ record, classify the bases first.
- if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
- for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
- e = CXXRD->bases_end(); i != e; ++i) {
- assert(!i->isVirtual() && !i->getType()->isDependentType() &&
- "Unexpected base class!");
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
-
- // Classify this field.
- //
- // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate exceeds a
- // single eightbyte, each is classified separately. Each eightbyte gets
- // initialized to class NO_CLASS.
- Class FieldLo, FieldHi;
- uint64_t Offset = OffsetBase + Layout.getBaseClassOffset(Base);
- classify(i->getType(), Context, Offset, FieldLo, FieldHi);
- Lo = merge(Lo, FieldLo);
- Hi = merge(Hi, FieldHi);
- if (Lo == Memory || Hi == Memory)
- break;
- }
-
- // If this record has no fields but isn't empty, classify as INTEGER.
- if (RD->field_empty() && Size)
- Current = Integer;
- }
-
- // Classify the fields one at a time, merging the results.
- unsigned idx = 0;
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i, ++idx) {
- uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
- bool BitField = i->isBitField();
-
- // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
- // fields, it has class MEMORY.
- //
- // Note, skip this test for bit-fields, see below.
- if (!BitField && Offset % Context.getTypeAlign(i->getType())) {
- Lo = Memory;
- return;
- }
-
- // Classify this field.
- //
- // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate
- // exceeds a single eightbyte, each is classified
- // separately. Each eightbyte gets initialized to class
- // NO_CLASS.
- Class FieldLo, FieldHi;
-
- // Bit-fields require special handling, they do not force the
- // structure to be passed in memory even if unaligned, and
- // therefore they can straddle an eightbyte.
- if (BitField) {
- // Ignore padding bit-fields.
- if (i->isUnnamedBitfield())
- continue;
-
- uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
- uint64_t Size = i->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
-
- uint64_t EB_Lo = Offset / 64;
- uint64_t EB_Hi = (Offset + Size - 1) / 64;
- FieldLo = FieldHi = NoClass;
- if (EB_Lo) {
- assert(EB_Hi == EB_Lo && "Invalid classification, type > 16 bytes.");
- FieldLo = NoClass;
- FieldHi = Integer;
- } else {
- FieldLo = Integer;
- FieldHi = EB_Hi ? Integer : NoClass;
- }
- } else
- classify(i->getType(), Context, Offset, FieldLo, FieldHi);
- Lo = merge(Lo, FieldLo);
- Hi = merge(Hi, FieldHi);
- if (Lo == Memory || Hi == Memory)
- break;
- }
-
- // AMD64-ABI 3.2.3p2: Rule 5. Then a post merger cleanup is done:
- //
- // (a) If one of the classes is MEMORY, the whole argument is
- // passed in memory.
- //
- // (b) If SSEUP is not preceeded by SSE, it is converted to SSE.
-
- // The first of these conditions is guaranteed by how we implement
- // the merge (just bail).
- //
- // The second condition occurs in the case of unions; for example
- // union { _Complex double; unsigned; }.
- if (Hi == Memory)
- Lo = Memory;
- if (Hi == SSEUp && Lo != SSE)
- Hi = SSE;
- }
-}
-
-ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty,
- const llvm::Type *CoerceTo,
- ASTContext &Context) const {
- if (CoerceTo == llvm::Type::getInt64Ty(CoerceTo->getContext())) {
- // Integer and pointer types will end up in a general purpose
- // register.
- if (Ty->isIntegralType() || Ty->hasPointerRepresentation())
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- } else if (CoerceTo == llvm::Type::getDoubleTy(CoerceTo->getContext())) {
- // FIXME: It would probably be better to make CGFunctionInfo only map using
- // canonical types than to canonize here.
- QualType CTy = Context.getCanonicalType(Ty);
-
- // Float and double end up in a single SSE reg.
- if (CTy == Context.FloatTy || CTy == Context.DoubleTy)
- return ABIArgInfo::getDirect();
-
- }
-
- return ABIArgInfo::getCoerce(CoerceTo);
-}
-
-ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
- ASTContext &Context) const {
- // If this is a scalar LLVM value then assume LLVM will pass it in the right
- // place naturally.
- if (!CodeGenFunction::hasAggregateLLVMType(Ty))
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
-
- bool ByVal = !isRecordWithNonTrivialDestructorOrCopyConstructor(Ty);
-
- // FIXME: Set alignment correctly.
- return ABIArgInfo::getIndirect(0, ByVal);
-}
-
-ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
- // classification algorithm.
- X86_64ABIInfo::Class Lo, Hi;
- classify(RetTy, Context, 0, Lo, Hi);
-
- // Check some invariants.
- assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
- assert((Lo != NoClass || Hi == NoClass) && "Invalid null classification.");
- assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
-
- const llvm::Type *ResType = 0;
- switch (Lo) {
- case NoClass:
- return ABIArgInfo::getIgnore();
-
- case SSEUp:
- case X87Up:
- assert(0 && "Invalid classification for lo word.");
-
- // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via
- // hidden argument.
- case Memory:
- return getIndirectResult(RetTy, Context);
-
- // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next
- // available register of the sequence %rax, %rdx is used.
- case Integer:
- ResType = llvm::Type::getInt64Ty(VMContext); break;
-
- // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next
- // available SSE register of the sequence %xmm0, %xmm1 is used.
- case SSE:
- ResType = llvm::Type::getDoubleTy(VMContext); break;
-
- // AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is
- // returned on the X87 stack in %st0 as 80-bit x87 number.
- case X87:
- ResType = llvm::Type::getX86_FP80Ty(VMContext); break;
-
- // AMD64-ABI 3.2.3p4: Rule 8. If the class is COMPLEX_X87, the real
- // part of the value is returned in %st0 and the imaginary part in
- // %st1.
- case ComplexX87:
- assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification.");
- ResType = llvm::StructType::get(VMContext, llvm::Type::getX86_FP80Ty(VMContext),
- llvm::Type::getX86_FP80Ty(VMContext),
- NULL);
- break;
- }
-
- switch (Hi) {
- // Memory was handled previously and X87 should
- // never occur as a hi class.
- case Memory:
- case X87:
- assert(0 && "Invalid classification for hi word.");
-
- case ComplexX87: // Previously handled.
- case NoClass: break;
-
- case Integer:
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getInt64Ty(VMContext), NULL);
- break;
- case SSE:
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getDoubleTy(VMContext), NULL);
- break;
-
- // AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte
- // is passed in the upper half of the last used SSE register.
- //
- // SSEUP should always be preceeded by SSE, just widen.
- case SSEUp:
- assert(Lo == SSE && "Unexpected SSEUp classification.");
- ResType = llvm::VectorType::get(llvm::Type::getDoubleTy(VMContext), 2);
- break;
-
- // AMD64-ABI 3.2.3p4: Rule 7. If the class is X87UP, the value is
- // returned together with the previous X87 value in %st0.
- case X87Up:
- // If X87Up is preceeded by X87, we don't need to do
- // anything. However, in some cases with unions it may not be
- // preceeded by X87. In such situations we follow gcc and pass the
- // extra bits in an SSE reg.
- if (Lo != X87)
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getDoubleTy(VMContext), NULL);
- break;
- }
-
- return getCoerceResult(RetTy, ResType, Context);
-}
-
-ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- unsigned &neededInt,
- unsigned &neededSSE) const {
- X86_64ABIInfo::Class Lo, Hi;
- classify(Ty, Context, 0, Lo, Hi);
-
- // Check some invariants.
- // FIXME: Enforce these by construction.
- assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
- assert((Lo != NoClass || Hi == NoClass) && "Invalid null classification.");
- assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
-
- neededInt = 0;
- neededSSE = 0;
- const llvm::Type *ResType = 0;
- switch (Lo) {
- case NoClass:
- return ABIArgInfo::getIgnore();
-
- // AMD64-ABI 3.2.3p3: Rule 1. If the class is MEMORY, pass the argument
- // on the stack.
- case Memory:
-
- // AMD64-ABI 3.2.3p3: Rule 5. If the class is X87, X87UP or
- // COMPLEX_X87, it is passed in memory.
- case X87:
- case ComplexX87:
- return getIndirectResult(Ty, Context);
-
- case SSEUp:
- case X87Up:
- assert(0 && "Invalid classification for lo word.");
-
- // AMD64-ABI 3.2.3p3: Rule 2. If the class is INTEGER, the next
- // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8
- // and %r9 is used.
- case Integer:
- ++neededInt;
- ResType = llvm::Type::getInt64Ty(VMContext);
- break;
-
- // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next
- // available SSE register is used, the registers are taken in the
- // order from %xmm0 to %xmm7.
- case SSE:
- ++neededSSE;
- ResType = llvm::Type::getDoubleTy(VMContext);
- break;
- }
-
- switch (Hi) {
- // Memory was handled previously, ComplexX87 and X87 should
- // never occur as hi classes, and X87Up must be preceed by X87,
- // which is passed in memory.
- case Memory:
- case X87:
- case ComplexX87:
- assert(0 && "Invalid classification for hi word.");
- break;
-
- case NoClass: break;
- case Integer:
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getInt64Ty(VMContext), NULL);
- ++neededInt;
- break;
-
- // X87Up generally doesn't occur here (long double is passed in
- // memory), except in situations involving unions.
- case X87Up:
- case SSE:
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getDoubleTy(VMContext), NULL);
- ++neededSSE;
- break;
-
- // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the
- // eightbyte is passed in the upper half of the last used SSE
- // register.
- case SSEUp:
- assert(Lo == SSE && "Unexpected SSEUp classification.");
- ResType = llvm::VectorType::get(llvm::Type::getDoubleTy(VMContext), 2);
- break;
- }
-
- return getCoerceResult(Ty, ResType, Context);
-}
-
-void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(),
- Context, VMContext);
-
- // Keep track of the number of assigned registers.
- unsigned freeIntRegs = 6, freeSSERegs = 8;
-
- // If the return value is indirect, then the hidden argument is consuming one
- // integer register.
- if (FI.getReturnInfo().isIndirect())
- --freeIntRegs;
-
- // AMD64-ABI 3.2.3p3: Once arguments are classified, the registers
- // get assigned (in left-to-right order) for passing as follows...
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it) {
- unsigned neededInt, neededSSE;
- it->info = classifyArgumentType(it->type, Context, VMContext,
- neededInt, neededSSE);
-
- // AMD64-ABI 3.2.3p3: If there are no registers available for any
- // eightbyte of an argument, the whole argument is passed on the
- // stack. If registers have already been assigned for some
- // eightbytes of such an argument, the assignments get reverted.
- if (freeIntRegs >= neededInt && freeSSERegs >= neededSSE) {
- freeIntRegs -= neededInt;
- freeSSERegs -= neededSSE;
- } else {
- it->info = getIndirectResult(it->type, Context);
- }
- }
-}
-
-static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr,
- QualType Ty,
- CodeGenFunction &CGF) {
- llvm::Value *overflow_arg_area_p =
- CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_p");
- llvm::Value *overflow_arg_area =
- CGF.Builder.CreateLoad(overflow_arg_area_p, "overflow_arg_area");
-
- // AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16
- // byte boundary if alignment needed by type exceeds 8 byte boundary.
- uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
- if (Align > 8) {
- // Note that we follow the ABI & gcc here, even though the type
- // could in theory have an alignment greater than 16. This case
- // shouldn't ever matter in practice.
-
- // overflow_arg_area = (overflow_arg_area + 15) & ~15;
- llvm::Value *Offset =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), 15);
- overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset);
- llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(overflow_arg_area,
- llvm::Type::getInt64Ty(CGF.getLLVMContext()));
- llvm::Value *Mask = llvm::ConstantInt::get(
- llvm::Type::getInt64Ty(CGF.getLLVMContext()), ~15LL);
- overflow_arg_area =
- CGF.Builder.CreateIntToPtr(CGF.Builder.CreateAnd(AsInt, Mask),
- overflow_arg_area->getType(),
- "overflow_arg_area.align");
- }
-
- // AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area.
- const llvm::Type *LTy = CGF.ConvertTypeForMem(Ty);
- llvm::Value *Res =
- CGF.Builder.CreateBitCast(overflow_arg_area,
- llvm::PointerType::getUnqual(LTy));
-
- // AMD64-ABI 3.5.7p5: Step 9. Set l->overflow_arg_area to:
- // l->overflow_arg_area + sizeof(type).
- // AMD64-ABI 3.5.7p5: Step 10. Align l->overflow_arg_area upwards to
- // an 8 byte boundary.
-
- uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
- llvm::Value *Offset =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()),
- (SizeInBytes + 7) & ~7);
- overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset,
- "overflow_arg_area.next");
- CGF.Builder.CreateStore(overflow_arg_area, overflow_arg_area_p);
-
- // AMD64-ABI 3.5.7p5: Step 11. Return the fetched type.
- return Res;
-}
-
-llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- llvm::LLVMContext &VMContext = CGF.getLLVMContext();
- const llvm::Type *i32Ty = llvm::Type::getInt32Ty(VMContext);
- const llvm::Type *DoubleTy = llvm::Type::getDoubleTy(VMContext);
-
- // Assume that va_list type is correct; should be pointer to LLVM type:
- // struct {
- // i32 gp_offset;
- // i32 fp_offset;
- // i8* overflow_arg_area;
- // i8* reg_save_area;
- // };
- unsigned neededInt, neededSSE;
- ABIArgInfo AI = classifyArgumentType(Ty, CGF.getContext(), VMContext,
- neededInt, neededSSE);
-
- // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
- // in the registers. If not go to step 7.
- if (!neededInt && !neededSSE)
- return EmitVAArgFromMemory(VAListAddr, Ty, CGF);
-
- // AMD64-ABI 3.5.7p5: Step 2. Compute num_gp to hold the number of
- // general purpose registers needed to pass type and num_fp to hold
- // the number of floating point registers needed.
-
- // AMD64-ABI 3.5.7p5: Step 3. Verify whether arguments fit into
- // registers. In the case: l->gp_offset > 48 - num_gp * 8 or
- // l->fp_offset > 304 - num_fp * 16 go to step 7.
- //
- // NOTE: 304 is a typo, there are (6 * 8 + 8 * 16) = 176 bytes of
- // register save space).
-
- llvm::Value *InRegs = 0;
- llvm::Value *gp_offset_p = 0, *gp_offset = 0;
- llvm::Value *fp_offset_p = 0, *fp_offset = 0;
- if (neededInt) {
- gp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "gp_offset_p");
- gp_offset = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset");
- InRegs =
- CGF.Builder.CreateICmpULE(gp_offset,
- llvm::ConstantInt::get(i32Ty,
- 48 - neededInt * 8),
- "fits_in_gp");
- }
-
- if (neededSSE) {
- fp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 1, "fp_offset_p");
- fp_offset = CGF.Builder.CreateLoad(fp_offset_p, "fp_offset");
- llvm::Value *FitsInFP =
- CGF.Builder.CreateICmpULE(fp_offset,
- llvm::ConstantInt::get(i32Ty,
- 176 - neededSSE * 16),
- "fits_in_fp");
- InRegs = InRegs ? CGF.Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
- }
-
- llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
- llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem");
- llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
- CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
-
- // Emit code to load the value if it was passed in registers.
-
- CGF.EmitBlock(InRegBlock);
-
- // AMD64-ABI 3.5.7p5: Step 4. Fetch type from l->reg_save_area with
- // an offset of l->gp_offset and/or l->fp_offset. This may require
- // copying to a temporary location in case the parameter is passed
- // in different register classes or requires an alignment greater
- // than 8 for general purpose registers and 16 for XMM registers.
- //
- // FIXME: This really results in shameful code when we end up needing to
- // collect arguments from different places; often what should result in a
- // simple assembling of a structure from scattered addresses has many more
- // loads than necessary. Can we clean this up?
- const llvm::Type *LTy = CGF.ConvertTypeForMem(Ty);
- llvm::Value *RegAddr =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(VAListAddr, 3),
- "reg_save_area");
- if (neededInt && neededSSE) {
- // FIXME: Cleanup.
- assert(AI.isCoerce() && "Unexpected ABI info for mixed regs");
- const llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType());
- llvm::Value *Tmp = CGF.CreateTempAlloca(ST);
- assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs");
- const llvm::Type *TyLo = ST->getElementType(0);
- const llvm::Type *TyHi = ST->getElementType(1);
- assert((TyLo->isFloatingPoint() ^ TyHi->isFloatingPoint()) &&
- "Unexpected ABI info for mixed regs");
- const llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo);
- const llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi);
- llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
- llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
- llvm::Value *RegLoAddr = TyLo->isFloatingPoint() ? FPAddr : GPAddr;
- llvm::Value *RegHiAddr = TyLo->isFloatingPoint() ? GPAddr : FPAddr;
- llvm::Value *V =
- CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
- V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegHiAddr, PTyHi));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
-
- RegAddr = CGF.Builder.CreateBitCast(Tmp,
- llvm::PointerType::getUnqual(LTy));
- } else if (neededInt) {
- RegAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
- RegAddr = CGF.Builder.CreateBitCast(RegAddr,
- llvm::PointerType::getUnqual(LTy));
- } else {
- if (neededSSE == 1) {
- RegAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
- RegAddr = CGF.Builder.CreateBitCast(RegAddr,
- llvm::PointerType::getUnqual(LTy));
- } else {
- assert(neededSSE == 2 && "Invalid number of needed registers!");
- // SSE registers are spaced 16 bytes apart in the register save
- // area, we need to collect the two eightbytes together.
- llvm::Value *RegAddrLo = CGF.Builder.CreateGEP(RegAddr, fp_offset);
- llvm::Value *RegAddrHi =
- CGF.Builder.CreateGEP(RegAddrLo,
- llvm::ConstantInt::get(i32Ty, 16));
- const llvm::Type *DblPtrTy =
- llvm::PointerType::getUnqual(DoubleTy);
- const llvm::StructType *ST = llvm::StructType::get(VMContext, DoubleTy,
- DoubleTy, NULL);
- llvm::Value *V, *Tmp = CGF.CreateTempAlloca(ST);
- V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo,
- DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
- V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrHi,
- DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
- RegAddr = CGF.Builder.CreateBitCast(Tmp,
- llvm::PointerType::getUnqual(LTy));
- }
- }
-
- // AMD64-ABI 3.5.7p5: Step 5. Set:
- // l->gp_offset = l->gp_offset + num_gp * 8
- // l->fp_offset = l->fp_offset + num_fp * 16.
- if (neededInt) {
- llvm::Value *Offset = llvm::ConstantInt::get(i32Ty, neededInt * 8);
- CGF.Builder.CreateStore(CGF.Builder.CreateAdd(gp_offset, Offset),
- gp_offset_p);
- }
- if (neededSSE) {
- llvm::Value *Offset = llvm::ConstantInt::get(i32Ty, neededSSE * 16);
- CGF.Builder.CreateStore(CGF.Builder.CreateAdd(fp_offset, Offset),
- fp_offset_p);
- }
- CGF.EmitBranch(ContBlock);
-
- // Emit code to load the value if it was passed in memory.
-
- CGF.EmitBlock(InMemBlock);
- llvm::Value *MemAddr = EmitVAArgFromMemory(VAListAddr, Ty, CGF);
-
- // Return the appropriate result.
-
- CGF.EmitBlock(ContBlock);
- llvm::PHINode *ResAddr = CGF.Builder.CreatePHI(RegAddr->getType(),
- "vaarg.addr");
- ResAddr->reserveOperandSpace(2);
- ResAddr->addIncoming(RegAddr, InRegBlock);
- ResAddr->addIncoming(MemAddr, InMemBlock);
-
- return ResAddr;
-}
-
-// PIC16 ABI Implementation
-
-namespace {
-
-class PIC16ABIInfo : public ABIInfo {
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
- }
-
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
-};
-
-}
-
-ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType()) {
- return ABIArgInfo::getIgnore();
- } else {
- return ABIArgInfo::getDirect();
- }
-}
-
-ABIArgInfo PIC16ABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- return ABIArgInfo::getDirect();
-}
-
-llvm::Value *PIC16ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- return 0;
-}
-
-// ARM ABI Implementation
-
-namespace {
-
-class ARMABIInfo : public ABIInfo {
-public:
- enum ABIKind {
- APCS = 0,
- AAPCS = 1,
- AAPCS_VFP
- };
-
-private:
- ABIKind Kind;
-
-public:
- ARMABIInfo(ABIKind _Kind) : Kind(_Kind) {}
-
-private:
- ABIKind getABIKind() const { return Kind; }
-
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMCOntext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
-};
-
-}
-
-void ARMABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it) {
- it->info = classifyArgumentType(it->type, Context, VMContext);
- }
-
- // ARM always overrides the calling convention.
- switch (getABIKind()) {
- case APCS:
- FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_APCS);
- break;
-
- case AAPCS:
- FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS);
- break;
-
- case AAPCS_VFP:
- FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS_VFP);
- break;
- }
-}
-
-ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (!CodeGenFunction::hasAggregateLLVMType(Ty))
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
-
- // Ignore empty records.
- if (isEmptyRecord(Context, Ty, true))
- return ABIArgInfo::getIgnore();
-
- // FIXME: This is kind of nasty... but there isn't much choice because the ARM
- // backend doesn't support byval.
- // FIXME: This doesn't handle alignment > 64 bits.
- const llvm::Type* ElemTy;
- unsigned SizeRegs;
- if (Context.getTypeAlign(Ty) > 32) {
- ElemTy = llvm::Type::getInt64Ty(VMContext);
- SizeRegs = (Context.getTypeSize(Ty) + 63) / 64;
- } else {
- ElemTy = llvm::Type::getInt32Ty(VMContext);
- SizeRegs = (Context.getTypeSize(Ty) + 31) / 32;
- }
- std::vector<const llvm::Type*> LLVMFields;
- LLVMFields.push_back(llvm::ArrayType::get(ElemTy, SizeRegs));
- const llvm::Type* STy = llvm::StructType::get(VMContext, LLVMFields, true);
- return ABIArgInfo::getCoerce(STy);
-}
-
-static bool isIntegerLikeType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) {
- // APCS, C Language Calling Conventions, Non-Simple Return Values: A structure
- // is called integer-like if its size is less than or equal to one word, and
- // the offset of each of its addressable sub-fields is zero.
-
- uint64_t Size = Context.getTypeSize(Ty);
-
- // Check that the type fits in a word.
- if (Size > 32)
- return false;
-
- // FIXME: Handle vector types!
- if (Ty->isVectorType())
- return false;
-
- // Float types are never treated as "integer like".
- if (Ty->isRealFloatingType())
- return false;
-
- // If this is a builtin or pointer type then it is ok.
- if (Ty->getAs<BuiltinType>() || Ty->isPointerType())
- return true;
-
- // Complex types "should" be ok by the definition above, but they are not.
- if (Ty->isAnyComplexType())
- return false;
-
- // Single element and zero sized arrays should be allowed, by the definition
- // above, but they are not.
-
- // Otherwise, it must be a record type.
- const RecordType *RT = Ty->getAs<RecordType>();
- if (!RT) return false;
-
- // Ignore records with flexible arrays.
- const RecordDecl *RD = RT->getDecl();
- if (RD->hasFlexibleArrayMember())
- return false;
-
- // Check that all sub-fields are at offset 0, and are themselves "integer
- // like".
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
- bool HadField = false;
- unsigned idx = 0;
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i, ++idx) {
- const FieldDecl *FD = *i;
-
- // Check if this field is at offset 0.
- uint64_t Offset = Layout.getFieldOffset(idx);
- if (Offset != 0) {
- // Allow padding bit-fields, but only if they are all at the end of the
- // structure (despite the wording above, this matches gcc).
- if (FD->isBitField() &&
- !FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) {
- for (; i != e; ++i)
- if (!i->isBitField() ||
- i->getBitWidth()->EvaluateAsInt(Context).getZExtValue())
- return false;
-
- // All remaining fields are padding, allow this.
- return true;
- }
-
- return false;
- }
-
- if (!isIntegerLikeType(FD->getType(), Context, VMContext))
- return false;
-
- // Only allow at most one field in a structure. Again this doesn't match the
- // wording above, but follows gcc.
- if (!RD->isUnion()) {
- if (HadField)
- return false;
-
- HadField = true;
- }
- }
-
- return true;
-}
-
-ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType())
- return ABIArgInfo::getIgnore();
-
- if (!CodeGenFunction::hasAggregateLLVMType(RetTy))
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
-
- // Are we following APCS?
- if (getABIKind() == APCS) {
- if (isEmptyRecord(Context, RetTy, false))
- return ABIArgInfo::getIgnore();
-
- // Integer like structures are returned in r0.
- if (isIntegerLikeType(RetTy, Context, VMContext)) {
- // Return in the smallest viable integer type.
- uint64_t Size = Context.getTypeSize(RetTy);
- if (Size <= 8)
- return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(VMContext));
- if (Size <= 16)
- return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(VMContext));
- return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(VMContext));
- }
-
- // Otherwise return in memory.
- return ABIArgInfo::getIndirect(0);
- }
-
- // Otherwise this is an AAPCS variant.
-
- if (isEmptyRecord(Context, RetTy, true))
- return ABIArgInfo::getIgnore();
-
- // Aggregates <= 4 bytes are returned in r0; other aggregates
- // are returned indirectly.
- uint64_t Size = Context.getTypeSize(RetTy);
- if (Size <= 32) {
- // Return in the smallest viable integer type.
- if (Size <= 8)
- return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(VMContext));
- if (Size <= 16)
- return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(VMContext));
- return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(VMContext));
- }
-
- return ABIArgInfo::getIndirect(0);
-}
-
-llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- // FIXME: Need to handle alignment
- const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
- const llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
-
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
- "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
- llvm::Type *PTy =
- llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
-
- uint64_t Offset =
- llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);
- llvm::Value *NextAddr =
- Builder.CreateGEP(Addr, llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(CGF.getLLVMContext()), Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
-
- return AddrTyped;
-}
-
-ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType()) {
- return ABIArgInfo::getIgnore();
- } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
- return ABIArgInfo::getIndirect(0);
- } else {
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
-}
-
-// SystemZ ABI Implementation
-
-namespace {
-
-class SystemZABIInfo : public ABIInfo {
- bool isPromotableIntegerType(QualType Ty) const;
-
- ABIArgInfo classifyReturnType(QualType RetTy, ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy, ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(),
- Context, VMContext);
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
- }
-
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
-};
-
-}
-
-bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const {
- // SystemZ ABI requires all 8, 16 and 32 bit quantities to be extended.
- if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
- switch (BT->getKind()) {
- case BuiltinType::Bool:
- case BuiltinType::Char_S:
- case BuiltinType::Char_U:
- case BuiltinType::SChar:
- case BuiltinType::UChar:
- case BuiltinType::Short:
- case BuiltinType::UShort:
- case BuiltinType::Int:
- case BuiltinType::UInt:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- // FIXME: Implement
- return 0;
-}
-
-
-ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType()) {
- return ABIArgInfo::getIgnore();
- } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
- return ABIArgInfo::getIndirect(0);
- } else {
- return (isPromotableIntegerType(RetTy) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
-}
-
-ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
- return ABIArgInfo::getIndirect(0);
- } else {
- return (isPromotableIntegerType(Ty) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
-}
-
-ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
- return ABIArgInfo::getIndirect(0);
- } else {
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
-}
-
-llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- return 0;
-}
-
-const ABIInfo &CodeGenTypes::getABIInfo() const {
- if (TheABIInfo)
- return *TheABIInfo;
-
- // For now we just cache the ABIInfo in CodeGenTypes and don't free it.
-
- const llvm::Triple &Triple(getContext().Target.getTriple());
- switch (Triple.getArch()) {
- default:
- return *(TheABIInfo = new DefaultABIInfo);
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- // FIXME: We want to know the float calling convention as well.
- if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0)
- return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::APCS));
-
- return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::AAPCS));
-
- case llvm::Triple::pic16:
- return *(TheABIInfo = new PIC16ABIInfo());
-
- case llvm::Triple::systemz:
- return *(TheABIInfo = new SystemZABIInfo());
-
- case llvm::Triple::x86:
- switch (Triple.getOS()) {
- case llvm::Triple::Darwin:
- return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
- case llvm::Triple::Cygwin:
- case llvm::Triple::MinGW32:
- case llvm::Triple::MinGW64:
- case llvm::Triple::AuroraUX:
- case llvm::Triple::DragonFly:
- case llvm::Triple::FreeBSD:
- case llvm::Triple::OpenBSD:
- return *(TheABIInfo = new X86_32ABIInfo(Context, false, true));
-
- default:
- return *(TheABIInfo = new X86_32ABIInfo(Context, false, false));
- }
-
- case llvm::Triple::x86_64:
- return *(TheABIInfo = new X86_64ABIInfo());
- }
-}
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index e5fd47ec2d16..4454662a9304 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -257,7 +257,7 @@ class DefaultABIInfo : public ABIInfo {
class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
public:
- DefaultTargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
+ DefaultTargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {}
};
llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -320,7 +320,7 @@ public:
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
public:
X86_32TargetCodeGenInfo(ASTContext &Context, bool d, bool p)
- :TargetCodeGenInfo(new X86_32ABIInfo(Context, d, p)) {};
+ :TargetCodeGenInfo(new X86_32ABIInfo(Context, d, p)) {}
};
}
@@ -619,7 +619,7 @@ public:
class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {};
+ X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {}
};
}
@@ -1428,7 +1428,7 @@ class PIC16ABIInfo : public ABIInfo {
class PIC16TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- PIC16TargetCodeGenInfo():TargetCodeGenInfo(new PIC16ABIInfo()) {};
+ PIC16TargetCodeGenInfo():TargetCodeGenInfo(new PIC16ABIInfo()) {}
};
}
@@ -1493,7 +1493,7 @@ private:
class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
public:
ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K)
- :TargetCodeGenInfo(new ARMABIInfo(K)) {};
+ :TargetCodeGenInfo(new ARMABIInfo(K)) {}
};
}
@@ -1754,7 +1754,7 @@ class SystemZABIInfo : public ABIInfo {
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
public:
- SystemZTargetCodeGenInfo():TargetCodeGenInfo(new SystemZABIInfo()) {};
+ SystemZTargetCodeGenInfo():TargetCodeGenInfo(new SystemZABIInfo()) {}
};
}
@@ -1816,7 +1816,7 @@ namespace {
class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- MSP430TargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
+ MSP430TargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {}
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const;
};
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index 495b22fc284a..58b7b79224fd 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -34,7 +34,7 @@ namespace clang {
ABIInfo *Info;
public:
// WARNING: Acquires the ownership of ABIInfo.
- TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { };
+ TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { }
virtual ~TargetCodeGenInfo();
/// getABIInfo() - Returns ABI info helper for the target.
@@ -43,7 +43,7 @@ namespace clang {
/// SetTargetAttributes - Provides a convenient hook to handle extra
/// target-specific attributes for the given global.
virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const { };
+ CodeGen::CodeGenModule &M) const { }
};
}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index ab4bd49dd653..852a018e10f4 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -26,6 +26,7 @@
#include "clang/Basic/Version.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
@@ -66,6 +67,14 @@ Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
CCCUseClangCXX = false;
}
+
+ // Compute the path to the resource directory.
+ llvm::sys::Path P(Dir);
+ P.eraseComponent(); // Remove /bin from foo/bin
+ P.appendComponent("lib");
+ P.appendComponent("clang");
+ P.appendComponent(CLANG_VERSION_STRING);
+ ResourceDir = P.str();
}
Driver::~Driver() {
@@ -273,15 +282,7 @@ void Driver::PrintHelp(bool ShowHidden) const {
void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const {
// FIXME: The following handlers should use a callback mechanism, we don't
// know what the client would like to do.
-#ifdef CLANG_VENDOR
- OS << CLANG_VENDOR;
-#endif
- OS << "clang version " CLANG_VERSION_STRING " ("
- << getClangSubversionPath();
- if (unsigned Revision = getClangSubversionRevision())
- OS << " " << Revision;
- OS << ")" << '\n';
-
+ OS << getClangFullVersion() << '\n';
const ToolChain &TC = C.getDefaultToolChain();
OS << "Target: " << TC.getTripleString() << '\n';
@@ -675,7 +676,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
}
// Build the pipeline for this file.
- Action *Current = new InputAction(*InputArg, InputType);
+ llvm::OwningPtr<Action> Current(new InputAction(*InputArg, InputType));
for (unsigned i = 0; i != NumSteps; ++i) {
phases::ID Phase = types::getCompilationPhase(InputType, i);
@@ -686,8 +687,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
// Queue linker inputs.
if (Phase == phases::Link) {
assert(i + 1 == NumSteps && "linking must be final compilation step.");
- LinkerInputs.push_back(Current);
- Current = 0;
+ LinkerInputs.push_back(Current.take());
break;
}
@@ -698,14 +698,14 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
continue;
// Otherwise construct the appropriate action.
- Current = ConstructPhaseAction(Args, Phase, Current);
+ Current.reset(ConstructPhaseAction(Args, Phase, Current.take()));
if (Current->getType() == types::TY_Nothing)
break;
}
// If we ended with something, add to the output list.
if (Current)
- Actions.push_back(Current);
+ Actions.push_back(Current.take());
}
// Add a link action if necessary.
diff --git a/lib/Driver/Makefile b/lib/Driver/Makefile
index 4c3ca5ca8446..dbacf8be0141 100644
--- a/lib/Driver/Makefile
+++ b/lib/Driver/Makefile
@@ -13,8 +13,5 @@ BUILD_ARCHIVE = 1
CXXFLAGS = -fno-rtti
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
-ifdef CLANG_VENDOR
-CPPFLAGS += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
-endif
include $(LEVEL)/Makefile.common
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 42657d939a9b..a9c6a68ceb8a 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -47,6 +47,69 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
IPhoneOSVersionMin = "3.0";
}
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMArch(llvm::StringRef Value) {
+ if (Value == "armv6k")
+ return "armv6";
+
+ if (Value == "armv5tej")
+ return "armv5";
+
+ if (Value == "xscale")
+ return "xscale";
+
+ if (Value == "armv4t")
+ return "armv4t";
+
+ if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" ||
+ Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" ||
+ Value == "armv7m")
+ return "armv7";
+
+ return 0;
+}
+
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMCpu(llvm::StringRef Value) {
+ if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" ||
+ Value == "arm946e-s" || Value == "arm966e-s" ||
+ Value == "arm968e-s" || Value == "arm10e" ||
+ Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" ||
+ Value == "arm1026ej-s")
+ return "armv5";
+
+ if (Value == "xscale")
+ return "xscale";
+
+ if (Value == "arm1136j-s" || Value == "arm1136jf-s" ||
+ Value == "arm1176jz-s" || Value == "arm1176jzf-s")
+ return "armv6";
+
+ if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3")
+ return "armv7";
+
+ return 0;
+}
+
+llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
+ switch (getTriple().getArch()) {
+ default:
+ return getArchName();
+
+ case llvm::Triple::arm: {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ if (const char *Arch = GetArmArchForMArch(A->getValue(Args)))
+ return Arch;
+
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ if (const char *Arch = GetArmArchForMCpu(A->getValue(Args)))
+ return Arch;
+
+ return "arm";
+ }
+ }
+}
+
DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
const unsigned (&DarwinVersion)[3],
const unsigned (&_GCCVersion)[3], bool IsIPhoneOS)
@@ -118,10 +181,6 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
Path += ToolChainDir;
getProgramPaths().push_back(Path);
- Path = getDriver().Dir;
- Path += "/../libexec";
- getProgramPaths().push_back(Path);
-
getProgramPaths().push_back(getDriver().Dir);
}
@@ -235,13 +294,6 @@ DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
bool IsIPhoneOS)
: Darwin(Host, Triple, DarwinVersion, IsIPhoneOS)
{
- // Add the relative libexec dir (for clang-cc).
- //
- // FIXME: We should sink clang-cc into libexec/clang/<version>/.
- std::string Path = getDriver().Dir;
- Path += "/../libexec";
- getProgramPaths().push_back(Path);
-
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().Dir);
}
@@ -253,12 +305,10 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- // Check for static linking.
- if (Args.hasArg(options::OPT_static)) {
- // FIXME: We need to have compiler-rt available (perhaps as
- // libclang_static.a) to link against.
+ // Darwin doesn't support real static executables, don't link any runtime
+ // libraries with -static.
+ if (Args.hasArg(options::OPT_static))
return;
- }
// Reject -static-libgcc for now, we can deal with this when and if someone
// cares. This is useful in situations where someone wants to statically link
@@ -269,12 +319,52 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
return;
}
- // Otherwise link libSystem, which should have the support routines.
- //
- // FIXME: This is only true for 10.6 and beyond. Legacy support isn't
- // critical, but it should work... we should just link in the static
- // compiler-rt library.
+ // Otherwise link libSystem, then the dynamic runtime library, and finally any
+ // target specific static runtime library.
CmdArgs.push_back("-lSystem");
+
+ // Select the dynamic runtime library and the target specific static library.
+ const char *DarwinStaticLib = 0;
+ if (isIPhoneOS()) {
+ CmdArgs.push_back("-lgcc_s.1");
+
+ // We may need some static functions for armv6/thumb which are required to
+ // be in the same linkage unit as their caller.
+ if (getDarwinArchName(Args) == "armv6")
+ DarwinStaticLib = "libclang_rt.armv6.a";
+ } else {
+ unsigned MacosxVersionMin[3];
+ getMacosxVersionMin(Args, MacosxVersionMin);
+
+ // The dynamic runtime library was merged with libSystem for 10.6 and
+ // beyond; only 10.4 and 10.5 need an additional runtime library.
+ if (isMacosxVersionLT(MacosxVersionMin, 10, 5))
+ CmdArgs.push_back("-lgcc_s.10.4");
+ else if (isMacosxVersionLT(MacosxVersionMin, 10, 6))
+ CmdArgs.push_back("-lgcc_s.10.5");
+
+ // For OS X, we only need a static runtime library when targetting 10.4, to
+ // provide versions of the static functions which were omitted from
+ // 10.4.dylib.
+ if (isMacosxVersionLT(MacosxVersionMin, 10, 5))
+ DarwinStaticLib = "libclang_rt.10.4.a";
+ }
+
+ /// Add the target specific static library, if needed.
+ if (DarwinStaticLib) {
+ llvm::sys::Path P(getDriver().ResourceDir);
+ P.appendComponent("lib");
+ P.appendComponent("darwin");
+ P.appendComponent(DarwinStaticLib);
+
+ // For now, allow missing resource libraries to support developers who may
+ // not have compiler-rt checked out or integrated into their build.
+ if (!P.exists())
+ getDriver().Diag(clang::diag::warn_drv_missing_resource_library)
+ << P.str();
+ else
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+ }
}
void Darwin::getMacosxVersionMin(const ArgList &Args,
@@ -544,10 +634,6 @@ const char *Darwin::GetForcedPicModel() const {
Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
: ToolChain(Host, Triple) {
- std::string Path(getDriver().Dir);
- Path += "/../libexec";
- getProgramPaths().push_back(Path);
-
getProgramPaths().push_back(getDriver().Dir);
}
@@ -684,11 +770,6 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
- // Path mangling to find libexec
- std::string Path(getDriver().Dir);
-
- Path += "/../libexec";
- getProgramPaths().push_back(Path);
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
@@ -753,10 +834,6 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
// Path mangling to find libexec
- std::string Path(getDriver().Dir);
-
- Path += "/../libexec";
- getProgramPaths().push_back(Path);
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 374ad8c6bb81..3ca6ad88972c 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -85,6 +85,11 @@ public:
Res[2] = DarwinVersion[1];
}
+ /// getDarwinArchName - Get the "Darwin" arch name for a particular compiler
+ /// invocation. For example, Darwin treats different ARM variations as
+ /// distinct architectures.
+ llvm::StringRef getDarwinArchName(const ArgList &Args) const;
+
/// getMacosxVersionMin - Get the effective -mmacosx-version-min, which is
/// either the -mmacosx-version-min, or the current version if unspecified.
void getMacosxVersionMin(const ArgList &Args, unsigned (&Res)[3]) const;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 010953df5e0e..afb22a236767 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -9,7 +9,6 @@
#include "Tools.h"
-#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
@@ -864,15 +863,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
// Pass the path to compiler resource files.
- //
- // FIXME: Get this from a configuration object.
- llvm::sys::Path P(D.Dir);
- P.eraseComponent(); // Remove /bin from foo/bin
- P.appendComponent("lib");
- P.appendComponent("clang");
- P.appendComponent(CLANG_VERSION_STRING);
CmdArgs.push_back("-resource-dir");
- CmdArgs.push_back(Args.MakeArgString(P.str()));
+ CmdArgs.push_back(D.ResourceDir.c_str());
// Add preprocessing options like -I, -D, etc. if we are using the
// preprocessor.
@@ -1857,87 +1849,17 @@ static bool isSourceSuffix(const char *Str) {
.Default(false);
}
-// FIXME: Can we tablegen this?
-static const char *GetArmArchForMArch(llvm::StringRef Value) {
- if (Value == "armv6k")
- return "armv6";
-
- if (Value == "armv5tej")
- return "armv5";
-
- if (Value == "xscale")
- return "xscale";
-
- if (Value == "armv4t")
- return "armv4t";
-
- if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" ||
- Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" ||
- Value == "armv7m")
- return "armv7";
-
- return 0;
-}
-
-// FIXME: Can we tablegen this?
-static const char *GetArmArchForMCpu(llvm::StringRef Value) {
- if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" ||
- Value == "arm946e-s" || Value == "arm966e-s" ||
- Value == "arm968e-s" || Value == "arm10e" ||
- Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" ||
- Value == "arm1026ej-s")
- return "armv5";
-
- if (Value == "xscale")
- return "xscale";
-
- if (Value == "arm1136j-s" || Value == "arm1136jf-s" ||
- Value == "arm1176jz-s" || Value == "arm1176jzf-s")
- return "armv6";
-
- if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3")
- return "armv7";
-
- return 0;
-}
-
void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
ArgStringList &CmdArgs) const {
+ llvm::StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);
+
// Derived from darwin_arch spec.
CmdArgs.push_back("-arch");
+ CmdArgs.push_back(Args.MakeArgString(ArchName));
- switch (getToolChain().getTriple().getArch()) {
- default:
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
- break;
-
- case llvm::Triple::arm: {
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- if (const char *Arch = GetArmArchForMArch(A->getValue(Args))) {
- CmdArgs.push_back(Arch);
- return;
- }
- }
-
- if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
- if (const char *Arch = GetArmArchForMCpu(A->getValue(Args))) {
- CmdArgs.push_back(Arch);
- return;
- }
- }
-
- CmdArgs.push_back("arm");
+ // FIXME: Is this needed anymore?
+ if (ArchName == "arm")
CmdArgs.push_back("-force_cpusubtype_ALL");
- return;
- }
- }
-}
-
-void darwin::DarwinTool::AddDarwinSubArch(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- // Derived from darwin_subarch spec, not sure what the distinction
- // exists for but at least for this chain it is the same.
- AddDarwinArch(Args, CmdArgs);
}
void darwin::Link::AddLinkArgs(const ArgList &Args,
@@ -1954,11 +1876,9 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
}
if (!Args.hasArg(options::OPT_dynamiclib)) {
- if (Args.hasArg(options::OPT_force__cpusubtype__ALL)) {
- AddDarwinArch(Args, CmdArgs);
- CmdArgs.push_back("-force_cpusubtype_ALL");
- } else
- AddDarwinSubArch(Args, CmdArgs);
+ AddDarwinArch(Args, CmdArgs);
+ // FIXME: Why do this only on this path?
+ Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
Args.AddLastArg(CmdArgs, options::OPT_bundle);
Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
@@ -1992,11 +1912,7 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
"-dylib_current_version");
- if (Args.hasArg(options::OPT_force__cpusubtype__ALL)) {
- AddDarwinArch(Args, CmdArgs);
- // NOTE: We don't add -force_cpusubtype_ALL on this path. Ok.
- } else
- AddDarwinSubArch(Args, CmdArgs);
+ AddDarwinArch(Args, CmdArgs);
Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
"-dylib_install_name");
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 8f7da52c3119..abd8cfc6d42f 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -130,7 +130,6 @@ namespace darwin {
class VISIBILITY_HIDDEN DarwinTool : public Tool {
protected:
void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddDarwinSubArch(const ArgList &Args, ArgStringList &CmdArgs) const;
const toolchains::Darwin &getDarwinToolChain() const {
return reinterpret_cast<const toolchains::Darwin&>(getToolChain());
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 52b597e8d273..33cb94e02dc3 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -421,6 +421,11 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
Out << "<namespace alias> " << NAD->getNameAsString() << "\n";
break;
}
+ case Decl::ClassTemplate: {
+ ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
+ Out << "<class template> " << CTD->getNameAsString() << '\n';
+ break;
+ }
default:
Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
assert(0 && "decl unhandled");
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 48296c7289e3..2fb47cbd8a85 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -30,6 +30,7 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
using namespace clang;
@@ -103,11 +104,31 @@ const std::string &ASTUnit::getPCHFileName() {
ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
Diagnostic &Diags,
bool OnlyLocalDecls,
- bool UseBumpAllocator) {
+ bool UseBumpAllocator,
+ RemappedFile *RemappedFiles,
+ unsigned NumRemappedFiles) {
llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
+ for (unsigned I = 0; I != NumRemappedFiles; ++I) {
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile
+ = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
+ RemappedFiles[I].second->getBufferSize(),
+ 0);
+ if (!FromFile) {
+ Diags.Report(diag::err_fe_remap_missing_from_file)
+ << RemappedFiles[I].first;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ AST->getSourceManager().overrideFileContents(FromFile,
+ RemappedFiles[I].second);
+ }
+
// Gather Info for preprocessor construction later on.
LangOptions LangInfo;
@@ -289,7 +310,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
Diagnostic &Diags,
llvm::StringRef ResourceFilesPath,
bool OnlyLocalDecls,
- bool UseBumpAllocator) {
+ bool UseBumpAllocator,
+ RemappedFile *RemappedFiles,
+ unsigned NumRemappedFiles) {
llvm::SmallVector<const char *, 16> Args;
Args.push_back("<clang>"); // FIXME: Remove dummy argument.
Args.insert(Args.end(), ArgBegin, ArgEnd);
@@ -327,6 +350,11 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
(const char**) CCArgs.data()+CCArgs.size(),
Diags);
+ // Override any files that need remapping
+ for (unsigned I = 0; I != NumRemappedFiles; ++I)
+ CI.getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
+ RemappedFiles[I].second);
+
// Override the resources path.
CI.getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index ad152d33bcb2..45a3b15caecc 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -204,45 +204,47 @@ namespace llvm {
void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
switch (D->getKind()) {
- case Decl::Function: {
- FunctionDecl* FD = cast<FunctionDecl>(D);
+ case Decl::Function: {
+ FunctionDecl* FD = cast<FunctionDecl>(D);
- if (!Opts.AnalyzeSpecificFunction.empty() &&
- Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
- break;
-
- Stmt* Body = FD->getBody();
- if (Body) HandleCode(FD, Body, FunctionActions);
+ if (!Opts.AnalyzeSpecificFunction.empty() &&
+ Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
break;
- }
- case Decl::ObjCMethod: {
- ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
+ Stmt* Body = FD->getBody();
+ if (Body) HandleCode(FD, Body, FunctionActions);
+ break;
+ }
- if (Opts.AnalyzeSpecificFunction.size() > 0 &&
- Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
- return;
+ case Decl::ObjCMethod: {
+ ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
- Stmt* Body = MD->getBody();
- if (Body) HandleCode(MD, Body, ObjCMethodActions);
- break;
- }
+ if (Opts.AnalyzeSpecificFunction.size() > 0 &&
+ Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
+ return;
+
+ Stmt* Body = MD->getBody();
+ if (Body) HandleCode(MD, Body, ObjCMethodActions);
+ break;
+ }
- case Decl::CXXMethod: {
- CXXMethodDecl *CXXMD = cast<CXXMethodDecl>(D);
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::CXXMethod: {
+ CXXMethodDecl *CXXMD = cast<CXXMethodDecl>(D);
- if (Opts.AnalyzeSpecificFunction.size() > 0 &&
- Opts.AnalyzeSpecificFunction != CXXMD->getName())
- return;
+ if (Opts.AnalyzeSpecificFunction.size() > 0 &&
+ Opts.AnalyzeSpecificFunction != CXXMD->getName())
+ return;
- Stmt *Body = CXXMD->getBody();
- if (Body)
- HandleCode(CXXMD, Body, FunctionActions);
- break;
- }
+ Stmt *Body = CXXMD->getBody();
+ if (Body) HandleCode(CXXMD, Body, FunctionActions);
+ break;
+ }
- default:
- break;
+ default:
+ break;
}
}
@@ -409,20 +411,20 @@ static void ActionCheckerCFRef(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
switch (mgr.getLangOptions().getGCMode()) {
- default:
- assert (false && "Invalid GC mode.");
- case LangOptions::NonGC:
- ActionCheckerCFRefAux(C, mgr, D, false);
- break;
-
- case LangOptions::GCOnly:
- ActionCheckerCFRefAux(C, mgr, D, true);
- break;
-
- case LangOptions::HybridGC:
- ActionCheckerCFRefAux(C, mgr, D, false);
- ActionCheckerCFRefAux(C, mgr, D, true);
- break;
+ default:
+ assert (false && "Invalid GC mode.");
+ case LangOptions::NonGC:
+ ActionCheckerCFRefAux(C, mgr, D, false);
+ break;
+
+ case LangOptions::GCOnly:
+ ActionCheckerCFRefAux(C, mgr, D, true);
+ break;
+
+ case LangOptions::HybridGC:
+ ActionCheckerCFRefAux(C, mgr, D, false);
+ ActionCheckerCFRefAux(C, mgr, D, true);
+ break;
}
}
@@ -530,11 +532,11 @@ ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
switch (Opts.AnalysisList[i]) {
#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
- case NAME:\
- C->add ## SCOPE ## Action(&Action ## NAME);\
- break;
+ case NAME:\
+ C->add ## SCOPE ## Action(&Action ## NAME);\
+ break;
#include "clang/Frontend/Analyses.def"
- default: break;
+ default: break;
}
// Last, disable the effects of '-Werror' when using the AnalysisConsumer.
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index 7296246df21a..7326937e520a 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -77,25 +77,25 @@ public:
void EmitData(llvm::raw_ostream& Out) {
switch (Kind) {
- case IsFE:
- // Emit stat information.
- ::Emit32(Out, FE->getInode());
- ::Emit32(Out, FE->getDevice());
- ::Emit16(Out, FE->getFileMode());
- ::Emit64(Out, FE->getModificationTime());
- ::Emit64(Out, FE->getSize());
- break;
- case IsDE:
- // Emit stat information.
- ::Emit32(Out, (uint32_t) StatBuf->st_ino);
- ::Emit32(Out, (uint32_t) StatBuf->st_dev);
- ::Emit16(Out, (uint16_t) StatBuf->st_mode);
- ::Emit64(Out, (uint64_t) StatBuf->st_mtime);
- ::Emit64(Out, (uint64_t) StatBuf->st_size);
- delete StatBuf;
- break;
- default:
- break;
+ case IsFE:
+ // Emit stat information.
+ ::Emit32(Out, FE->getInode());
+ ::Emit32(Out, FE->getDevice());
+ ::Emit16(Out, FE->getFileMode());
+ ::Emit64(Out, FE->getModificationTime());
+ ::Emit64(Out, FE->getSize());
+ break;
+ case IsDE:
+ // Emit stat information.
+ ::Emit32(Out, (uint32_t) StatBuf->st_ino);
+ ::Emit32(Out, (uint32_t) StatBuf->st_dev);
+ ::Emit16(Out, (uint16_t) StatBuf->st_mode);
+ ::Emit64(Out, (uint64_t) StatBuf->st_mtime);
+ ::Emit64(Out, (uint64_t) StatBuf->st_size);
+ delete StatBuf;
+ break;
+ default:
+ break;
}
}
diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp
index b981fc41daa9..d7470d92a946 100644
--- a/lib/Frontend/DeclXML.cpp
+++ b/lib/Frontend/DeclXML.cpp
@@ -98,14 +98,14 @@ public:
const char* pAttributeName = NAME; \
const bool optional = false; \
switch (T->FN) { \
- default: assert(0 && "unknown enum value");
+ default: assert(0 && "unknown enum value");
#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
{ \
const char* pAttributeName = NAME; \
const bool optional = true; \
switch (T->FN) { \
- default: assert(0 && "unknown enum value");
+ default: assert(0 && "unknown enum value");
#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
#define END_ENUM_XML } }
diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp
index 93421ca4013d..b163e267b049 100644
--- a/lib/Frontend/HTMLDiagnostics.cpp
+++ b/lib/Frontend/HTMLDiagnostics.cpp
@@ -349,10 +349,10 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
const char *Kind = 0;
switch (P.getKind()) {
- case PathDiagnosticPiece::Event: Kind = "Event"; break;
- case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
- // Setting Kind to "Control" is intentional.
- case PathDiagnosticPiece::Macro: Kind = "Control"; break;
+ case PathDiagnosticPiece::Event: Kind = "Event"; break;
+ case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
+ // Setting Kind to "Control" is intentional.
+ case PathDiagnosticPiece::Macro: Kind = "Control"; break;
}
std::string sbuf;
@@ -380,14 +380,14 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
switch (*I) {
- default:
- ++cnt;
- continue;
- case ' ':
- case '\t':
- case '\n':
- if (cnt > max_token) max_token = cnt;
- cnt = 0;
+ default:
+ ++cnt;
+ continue;
+ case ' ':
+ case '\t':
+ case '\n':
+ if (cnt > max_token) max_token = cnt;
+ cnt = 0;
}
if (cnt > max_token)
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 6fceb98567b0..6102760aef53 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -189,10 +189,12 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
llvm::StringRef Arch,
llvm::StringRef Version) {
- llvm::Twine localBase = Base + "/" + Arch + "/" + Version + "/include";
- AddPath(localBase, System, true, false, false);
- AddPath(localBase + "/c++", System, true, false, false);
- AddPath(localBase + "/c++/backward", System, true, false, false);
+ AddPath(Base + "/" + Arch + "/" + Version + "/include",
+ System, true, false, false);
+ AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
+ System, true, false, false);
+ AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
+ System, true, false, false);
}
// FIXME: This probably should goto to some platform utils place.
@@ -206,8 +208,8 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
// There can be additional characters in the component. Only the numberic
// characters are compared.
-bool getSystemRegistryString(const char *keyPath, const char *valueName,
- char *value, size_t maxLength) {
+static bool getSystemRegistryString(const char *keyPath, const char *valueName,
+ char *value, size_t maxLength) {
HKEY hRootKey = NULL;
HKEY hKey = NULL;
const char* subKey = NULL;
@@ -312,13 +314,13 @@ bool getSystemRegistryString(const char *keyPath, const char *valueName,
}
#else // _MSC_VER
// Read registry string.
-bool getSystemRegistryString(const char *, const char *, char *, size_t) {
+static bool getSystemRegistryString(const char*, const char*, char*, size_t) {
return(false);
}
#endif // _MSC_VER
// Get Visual Studio installation directory.
-bool getVisualStudioDir(std::string &path) {
+static bool getVisualStudioDir(std::string &path) {
char vsIDEInstallDir[256];
// Try the Windows registry first.
bool hasVCDir = getSystemRegistryString(
@@ -365,7 +367,7 @@ bool getVisualStudioDir(std::string &path) {
}
// Get Windows SDK installation directory.
-bool getWindowsSDKDir(std::string &path) {
+static bool getWindowsSDKDir(std::string &path) {
char windowsSDKInstallDir[256];
// Try the Windows registry.
bool hasSDKDir = getSystemRegistryString(
@@ -508,6 +510,10 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
"i386-redhat-linux","", "", triple);
+ // Fedora 10 x86_64
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
+ "x86_64-redhat-linux", "32", "", triple);
+
// Fedora 11
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
"i586-redhat-linux","", "", triple);
@@ -556,7 +562,7 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
"i686-pc-linux-gnu", "", "", triple);
break;
case llvm::Triple::FreeBSD:
- AddPath("/usr/include/c++/4.2", System, true, false, false);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
break;
case llvm::Triple::Solaris:
// Solaris - Fall though..
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index e4c380ae0edd..9aaf1320346f 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/Utils.h"
+#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
@@ -137,7 +138,10 @@ static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix,
"1.79769313486231580793728971405301e+308L",
"1.18973149535723176508575932662800702e+4932L");
- llvm::Twine DefPrefix = "__" + Prefix + "_";
+ llvm::SmallString<32> DefPrefix;
+ DefPrefix = "__";
+ DefPrefix += Prefix;
+ DefPrefix += "_";
Builder.defineMacro(DefPrefix + "DENORM_MIN__", DenormMin);
Builder.defineMacro(DefPrefix + "HAS_DENORM__");
@@ -420,40 +424,61 @@ static void InitializeFileRemapping(Diagnostic &Diags,
SourceManager &SourceMgr,
FileManager &FileMgr,
const PreprocessorOptions &InitOpts) {
- // Remap files in the source manager.
+ // Remap files in the source manager (with buffers).
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ Remap = InitOpts.remapped_file_buffer_begin(),
+ RemapEnd = InitOpts.remapped_file_buffer_end();
+ Remap != RemapEnd;
+ ++Remap) {
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+ Remap->second->getBufferSize(),
+ 0);
+ if (!FromFile) {
+ Diags.Report(diag::err_fe_remap_missing_from_file)
+ << Remap->first;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ SourceMgr.overrideFileContents(FromFile, Remap->second);
+ }
+
+ // Remap files in the source manager (with other files).
for (PreprocessorOptions::remapped_file_iterator
- Remap = InitOpts.remapped_file_begin(),
- RemapEnd = InitOpts.remapped_file_end();
+ Remap = InitOpts.remapped_file_begin(),
+ RemapEnd = InitOpts.remapped_file_end();
Remap != RemapEnd;
++Remap) {
// Find the file that we're mapping to.
const FileEntry *ToFile = FileMgr.getFile(Remap->second);
if (!ToFile) {
Diags.Report(diag::err_fe_remap_missing_to_file)
- << Remap->first << Remap->second;
+ << Remap->first << Remap->second;
continue;
}
-
+
// Create the file entry for the file that we're mapping from.
const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
ToFile->getSize(),
0);
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file)
- << Remap->first;
+ << Remap->first;
continue;
}
-
+
// Load the contents of the file we're mapping to.
std::string ErrorStr;
const llvm::MemoryBuffer *Buffer
- = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
+ = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
if (!Buffer) {
Diags.Report(diag::err_fe_error_opening)
- << Remap->second << ErrorStr;
+ << Remap->second << ErrorStr;
continue;
}
-
+
// Override the contents of the "from" file with the contents of
// the "to" file.
SourceMgr.overrideFileContents(FromFile, Buffer);
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 07d5a78beaeb..259355145aa3 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1399,17 +1399,10 @@ PCHReader::ReadPCHBlock() {
NumComments = BlobLen / sizeof(SourceRange);
break;
- case pch::SVN_BRANCH_REVISION: {
- unsigned CurRevision = getClangSubversionRevision();
- if (Record[0] && CurRevision && Record[0] != CurRevision) {
- Diag(Record[0] < CurRevision? diag::warn_pch_version_too_old
- : diag::warn_pch_version_too_new);
- return IgnorePCH;
- }
-
- const char *CurBranch = getClangSubversionPath();
- if (strncmp(CurBranch, BlobStart, BlobLen)) {
- std::string PCHBranch(BlobStart, BlobLen);
+ case pch::VERSION_CONTROL_BRANCH_REVISION: {
+ llvm::StringRef CurBranch = getClangFullRepositoryVersion();
+ llvm::StringRef PCHBranch(BlobStart, BlobLen);
+ if (CurBranch != PCHBranch) {
Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
return IgnorePCH;
}
@@ -1909,18 +1902,20 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
}
case pch::TYPE_FUNCTION_NO_PROTO: {
- if (Record.size() != 2) {
+ if (Record.size() != 3) {
Error("incorrect encoding of no-proto function type");
return QualType();
}
QualType ResultType = GetType(Record[0]);
- return Context->getFunctionNoProtoType(ResultType, Record[1]);
+ return Context->getFunctionNoProtoType(ResultType, Record[1],
+ (CallingConv)Record[2]);
}
case pch::TYPE_FUNCTION_PROTO: {
QualType ResultType = GetType(Record[0]);
bool NoReturn = Record[1];
- unsigned Idx = 2;
+ CallingConv CallConv = (CallingConv)Record[2];
+ unsigned Idx = 3;
unsigned NumParams = Record[Idx++];
llvm::SmallVector<QualType, 16> ParamTypes;
for (unsigned I = 0; I != NumParams; ++I)
@@ -1936,7 +1931,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
isVariadic, Quals, hasExceptionSpec,
hasAnyExceptionSpec, NumExceptions,
- Exceptions.data(), NoReturn);
+ Exceptions.data(), NoReturn, CallConv);
}
case pch::TYPE_UNRESOLVED_USING:
@@ -2040,7 +2035,13 @@ void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
}
void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
- TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ if (TL.needsExtraLocalData()) {
+ TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
+ TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
+ TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
+ TL.setModeAttr(Record[Idx++]);
+ }
}
void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 69343ed48c4b..4dc1318a3ee8 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -223,7 +223,12 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
Protocols.reserve(NumProtocols);
for (unsigned I = 0; I != NumProtocols; ++I)
Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
- ID->setProtocolList(Protocols.data(), NumProtocols, *Reader.getContext());
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
+ *Reader.getContext());
unsigned NumIvars = Record[Idx++];
llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
IVars.reserve(NumIvars);
@@ -253,7 +258,12 @@ void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
- PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+ *Reader.getContext());
}
void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
@@ -282,7 +292,12 @@ void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
- FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+ *Reader.getContext());
}
void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
@@ -293,9 +308,15 @@ void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
- CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+ *Reader.getContext());
CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
- CD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
@@ -305,6 +326,7 @@ void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
+ D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setType(Reader.GetType(Record[Idx++]));
// FIXME: stable encoding
D->setPropertyAttributes(
@@ -671,7 +693,8 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation());
break;
case pch::DECL_OBJC_CATEGORY:
- D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), 0);
+ D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(),
+ SourceLocation(), SourceLocation(), 0);
break;
case pch::DECL_OBJC_CATEGORY_IMPL:
D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0);
@@ -683,7 +706,8 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
case pch::DECL_OBJC_PROPERTY:
- D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
+ D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(),
+ QualType());
break;
case pch::DECL_OBJC_PROPERTY_IMPL:
D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(),
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index 138f1e141b09..21c9cbf17cd7 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -117,6 +117,12 @@ namespace {
unsigned VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
unsigned VisitCXXConstructExpr(CXXConstructExpr *E);
+ unsigned VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+ unsigned VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
+ unsigned VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
+ unsigned VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
+ unsigned VisitCXXConstCastExpr(CXXConstCastExpr *E);
+ unsigned VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
};
}
@@ -513,7 +519,7 @@ unsigned PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
unsigned PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
VisitCastExpr(E);
- E->setTypeAsWritten(Reader.GetType(Record[Idx++]));
+ E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(Record, Idx));
return 1;
}
@@ -527,6 +533,7 @@ unsigned PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
unsigned PCHStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
VisitExpr(E);
E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
E->setInitializer(cast<Expr>(StmtStack.back()));
E->setFileScope(Record[Idx++]);
return 1;
@@ -868,6 +875,35 @@ unsigned PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
return E->getNumArgs();
}
+unsigned PCHStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+ unsigned num = VisitExplicitCastExpr(E);
+ E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ return num;
+}
+
+unsigned PCHStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+ unsigned num = VisitExplicitCastExpr(E);
+ E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ return num;
+}
+
// Within the bitstream, expressions are stored in Reverse Polish
// Notation, with each of the subexpressions preceding the
// expression they are stored in. To evaluate expressions, we
@@ -1176,6 +1212,28 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) {
S = new (Context) CXXConstructExpr(Empty, *Context,
Record[PCHStmtReader::NumExprFields + 2]);
break;
+
+ case pch::EXPR_CXX_STATIC_CAST:
+ S = new (Context) CXXStaticCastExpr(Empty);
+ break;
+
+ case pch::EXPR_CXX_DYNAMIC_CAST:
+ S = new (Context) CXXDynamicCastExpr(Empty);
+ break;
+
+ case pch::EXPR_CXX_REINTERPRET_CAST:
+ S = new (Context) CXXReinterpretCastExpr(Empty);
+ break;
+
+ case pch::EXPR_CXX_CONST_CAST:
+ S = new (Context) CXXConstCastExpr(Empty);
+ break;
+
+ case pch::EXPR_CXX_FUNCTIONAL_CAST:
+ S = new (Context) CXXFunctionalCastExpr(Empty);
+ break;
+
+
}
// We hit a STMT_STOP, so we're done with this expression.
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 3f6841b54576..9909c95847ee 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -139,6 +139,8 @@ void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
Writer.AddTypeRef(T->getResultType(), Record);
Record.push_back(T->getNoReturnAttr());
+ // FIXME: need to stabilize encoding of calling convention...
+ Record.push_back(T->getCallConv());
}
void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
@@ -275,7 +277,13 @@ void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
}
void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
- Writer.AddSourceLocation(TL.getNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getBuiltinLoc(), Record);
+ if (TL.needsExtraLocalData()) {
+ Record.push_back(TL.getWrittenTypeSpec());
+ Record.push_back(TL.getWrittenSignSpec());
+ Record.push_back(TL.getWrittenWidthSpec());
+ Record.push_back(TL.hasModeAttr());
+ }
}
void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
@@ -535,7 +543,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(STAT_CACHE);
RECORD(EXT_VECTOR_DECLS);
RECORD(COMMENT_RANGES);
- RECORD(SVN_BRANCH_REVISION);
+ RECORD(VERSION_CONTROL_BRANCH_REVISION);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -699,16 +707,15 @@ void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
}
- // Subversion branch/version information.
- BitCodeAbbrev *SvnAbbrev = new BitCodeAbbrev();
- SvnAbbrev->Add(BitCodeAbbrevOp(pch::SVN_BRANCH_REVISION));
- SvnAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // SVN revision
- SvnAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
- unsigned SvnAbbrevCode = Stream.EmitAbbrev(SvnAbbrev);
+ // Repository branch/version information.
+ BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
+ RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION));
+ RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
+ unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev);
Record.clear();
- Record.push_back(pch::SVN_BRANCH_REVISION);
- Record.push_back(getClangSubversionRevision());
- Stream.EmitRecordWithBlob(SvnAbbrevCode, Record, getClangSubversionPath());
+ Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION);
+ Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
+ getClangFullRepositoryVersion());
}
/// \brief Write the LangOptions structure.
@@ -1263,7 +1270,7 @@ void PCHWriter::WriteType(QualType T) {
// For all of the concrete, non-dependent types, call the
// appropriate visitor function.
#define TYPE(Class, Base) \
- case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
+ case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 2dbcc27f95ba..020f69b3e669 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -223,6 +223,10 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
PEnd = D->protocol_end();
P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
+ for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+ PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
Record.push_back(D->ivar_size());
for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
IEnd = D->ivar_end(); I != IEnd; ++I)
@@ -251,6 +255,10 @@ void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
for (ObjCProtocolDecl::protocol_iterator
I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
Writer.AddDeclRef(*I, Record);
+ for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+ PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
Code = pch::DECL_OBJC_PROTOCOL;
}
@@ -272,9 +280,13 @@ void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
VisitDecl(D);
Record.push_back(D->protocol_size());
- for (ObjCProtocolDecl::protocol_iterator
+ for (ObjCForwardProtocolDecl::protocol_iterator
I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
Writer.AddDeclRef(*I, Record);
+ for (ObjCForwardProtocolDecl::protocol_loc_iterator
+ PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
}
@@ -282,11 +294,16 @@ void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
VisitObjCContainerDecl(D);
Writer.AddDeclRef(D->getClassInterface(), Record);
Record.push_back(D->protocol_size());
- for (ObjCProtocolDecl::protocol_iterator
+ for (ObjCCategoryDecl::protocol_iterator
I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
Writer.AddDeclRef(*I, Record);
+ for (ObjCCategoryDecl::protocol_loc_iterator
+ PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
Writer.AddDeclRef(D->getNextClassCategory(), Record);
- Writer.AddSourceLocation(D->getLocEnd(), Record);
+ Writer.AddSourceLocation(D->getAtLoc(), Record);
+ Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
Code = pch::DECL_OBJC_CATEGORY;
}
@@ -298,6 +315,7 @@ void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
+ Writer.AddSourceLocation(D->getAtLoc(), Record);
Writer.AddTypeRef(D->getType(), Record);
// FIXME: stable encoding
Record.push_back((unsigned)D->getPropertyAttributes());
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 4be9b817ed82..fdfdfefe08ef 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -112,6 +112,12 @@ namespace {
// C++ Statements
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
void VisitCXXConstructExpr(CXXConstructExpr *E);
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+ void VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
+ void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
+ void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
+ void VisitCXXConstCastExpr(CXXConstCastExpr *E);
+ void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
};
}
@@ -477,7 +483,7 @@ void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
VisitCastExpr(E);
- Writer.AddTypeRef(E->getTypeAsWritten(), Record);
+ Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record);
}
void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
@@ -490,6 +496,7 @@ void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLParenLoc(), Record);
+ Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
Writer.WriteSubStmt(E->getInitializer());
Record.push_back(E->isFileScope());
Code = pch::EXPR_COMPOUND_LITERAL;
@@ -795,6 +802,38 @@ void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
Code = pch::EXPR_CXX_CONSTRUCT;
}
+void PCHStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+}
+
+void PCHStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = pch::EXPR_CXX_STATIC_CAST;
+}
+
+void PCHStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = pch::EXPR_CXX_DYNAMIC_CAST;
+}
+
+void PCHStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = pch::EXPR_CXX_REINTERPRET_CAST;
+}
+
+void PCHStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = pch::EXPR_CXX_CONST_CAST;
+}
+
+void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = pch::EXPR_CXX_FUNCTIONAL_CAST;
+}
+
//===----------------------------------------------------------------------===//
// PCHWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
index 92cafe6d1cbe..98be869d2646 100644
--- a/lib/Frontend/PlistDiagnostics.cpp
+++ b/lib/Frontend/PlistDiagnostics.cpp
@@ -177,12 +177,12 @@ static llvm::raw_ostream& EmitString(llvm::raw_ostream& o,
for (std::string::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
char c = *I;
switch (c) {
- default: o << c; break;
- case '&': o << "&amp;"; break;
- case '<': o << "&lt;"; break;
- case '>': o << "&gt;"; break;
- case '\'': o << "&apos;"; break;
- case '\"': o << "&quot;"; break;
+ default: o << c; break;
+ case '&': o << "&amp;"; break;
+ case '<': o << "&lt;"; break;
+ case '>': o << "&gt;"; break;
+ case '\'': o << "&apos;"; break;
+ case '\"': o << "&quot;"; break;
}
}
o << "</string>";
@@ -289,16 +289,16 @@ static void ReportMacro(llvm::raw_ostream& o,
I!=E; ++I) {
switch ((*I)->getKind()) {
- default:
- break;
- case PathDiagnosticPiece::Event:
- ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
- indent);
- break;
- case PathDiagnosticPiece::Macro:
- ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
- indent);
- break;
+ default:
+ break;
+ case PathDiagnosticPiece::Event:
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
+ indent);
+ break;
+ case PathDiagnosticPiece::Macro:
+ ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
+ indent);
+ break;
}
}
}
@@ -310,18 +310,18 @@ static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
unsigned indent = 4;
switch (P.getKind()) {
- case PathDiagnosticPiece::ControlFlow:
- ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
- LangOpts, indent);
- break;
- case PathDiagnosticPiece::Event:
- ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
- indent);
- break;
- case PathDiagnosticPiece::Macro:
- ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
- indent);
- break;
+ case PathDiagnosticPiece::ControlFlow:
+ ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
+ LangOpts, indent);
+ break;
+ case PathDiagnosticPiece::Event:
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
+ indent);
+ break;
+ case PathDiagnosticPiece::Macro:
+ ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
+ indent);
+ break;
}
}
diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp
index 95afb908dfa1..a91dd8d55e92 100644
--- a/lib/Frontend/PrintParserCallbacks.cpp
+++ b/lib/Frontend/PrintParserCallbacks.cpp
@@ -65,6 +65,7 @@ namespace {
SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtocols,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
Out << __FUNCTION__ << "\n";
@@ -72,7 +73,8 @@ namespace {
ClassName, ClassLoc,
SuperName, SuperLoc,
ProtoRefs, NumProtocols,
- EndProtoLoc, AttrList);
+ ProtoLocs, EndProtoLoc,
+ AttrList);
}
/// ActOnForwardClassDeclaration -
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index d9708d8bced4..43deaee8c1db 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -22,7 +22,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/TokenConcatenation.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
@@ -443,13 +443,11 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
}
}
-namespace {
- struct SortMacrosByID {
- typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
- bool operator()(const id_macro_pair &LHS, const id_macro_pair &RHS) const {
- return LHS.first->getName() < RHS.first->getName();
- }
- };
+typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
+static int MacroIDCompare(const void* a, const void* b) {
+ const id_macro_pair *LHS = static_cast<const id_macro_pair*>(a);
+ const id_macro_pair *RHS = static_cast<const id_macro_pair*>(b);
+ return LHS->first->getName().compare(RHS->first->getName());
}
static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
@@ -461,11 +459,9 @@ static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
do PP.Lex(Tok);
while (Tok.isNot(tok::eof));
- std::vector<std::pair<IdentifierInfo*, MacroInfo*> > MacrosByID;
- for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
- I != E; ++I)
- MacrosByID.push_back(*I);
- std::sort(MacrosByID.begin(), MacrosByID.end(), SortMacrosByID());
+ llvm::SmallVector<id_macro_pair, 128>
+ MacrosByID(PP.macro_begin(), PP.macro_end());
+ llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
MacroInfo &MI = *MacrosByID[i].second;
@@ -473,7 +469,7 @@ static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
if (MI.isBuiltinMacro()) continue;
PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS);
- *OS << "\n";
+ *OS << '\n';
}
}
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index fc9401d29001..35d8dde8eaab 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -420,6 +420,14 @@ namespace {
}
}
};
+
+ // Helper function: create a CStyleCastExpr with trivial type source info.
+ CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
+ CastExpr::CastKind Kind, Expr *E) {
+ TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
+ return new (Ctx) CStyleCastExpr(Ty, Kind, E, TInfo,
+ SourceLocation(), SourceLocation());
+ }
}
void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
@@ -610,6 +618,7 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
Preamble += "#define __attribute__(X)\n";
+ Preamble += "#define __weak\n";
}
else {
Preamble += "#define __block\n";
@@ -824,6 +833,10 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
}
void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
+ // When method is a synthesized one, such as a getter/setter there is
+ // nothing to rewrite.
+ if (Method->isSynthesized())
+ return;
SourceLocation LocStart = Method->getLocStart();
SourceLocation LocEnd = Method->getLocEnd();
@@ -837,10 +850,9 @@ void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
}
void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
- SourceLocation Loc = prop->getLocation();
+ SourceLocation Loc = prop->getAtLoc();
ReplaceText(Loc, 0, "// ", 3);
-
// FIXME: handle properties that are declared across multiple lines.
}
@@ -1219,11 +1231,9 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
SourceLocation(), II);
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
- CastExpr *castExpr = new (Context) CStyleCastExpr(castT,
- CastExpr::CK_Unknown,
- IV->getBase(),
- castT,SourceLocation(),
- SourceLocation());
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+ CastExpr::CK_Unknown,
+ IV->getBase());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
IV->getBase()->getLocEnd(),
@@ -1267,11 +1277,9 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
SourceLocation(), II);
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
- CastExpr *castExpr = new (Context) CStyleCastExpr(castT,
- CastExpr::CK_Unknown,
- IV->getBase(),
- castT, SourceLocation(),
- SourceLocation());
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+ CastExpr::CK_Unknown,
+ IV->getBase());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
IV->getBase()->getLocEnd(), castExpr);
@@ -1584,12 +1592,9 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
std::string syncBuf;
syncBuf += " objc_sync_exit(";
- Expr *syncExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(),
- CastExpr::CK_Unknown,
- S->getSynchExpr(),
- Context->getObjCIdType(),
- SourceLocation(),
- SourceLocation());
+ Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CastExpr::CK_Unknown,
+ S->getSynchExpr());
std::string syncExprBufS;
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
syncExpr->printPretty(syncExprBuf, *Context, 0,
@@ -2332,11 +2337,8 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
Context->getPointerType(DRE->getType()),
SourceLocation());
// cast to NSConstantString *
- CastExpr *cast = new (Context) CStyleCastExpr(Exp->getType(),
- CastExpr::CK_Unknown,
- Unop, Exp->getType(),
- SourceLocation(),
- SourceLocation());
+ CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
+ CastExpr::CK_Unknown, Unop);
ReplaceStmt(Exp, cast);
// delete Exp; leak for now, see RewritePropertySetter() usage for more info.
return cast;
@@ -2465,13 +2467,12 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// set the receiver to self, the first argument to all methods.
InitExprs.push_back(
- new (Context) CStyleCastExpr(Context->getObjCIdType(),
- CastExpr::CK_Unknown,
+ NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CastExpr::CK_Unknown,
new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
Context->getObjCIdType(),
- SourceLocation()),
- Context->getObjCIdType(),
- SourceLocation(), SourceLocation())); // set the 'receiver'.
+ SourceLocation()))
+ ); // set the 'receiver'.
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
@@ -2484,10 +2485,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
ClsExprs.size());
// To turn off a warning, type-cast to 'id'
InitExprs.push_back( // set 'super class', using objc_getClass().
- new (Context) CStyleCastExpr(Context->getObjCIdType(),
- CastExpr::CK_Unknown,
- Cls, Context->getObjCIdType(),
- SourceLocation(), SourceLocation()));
+ NoTypeInfoCStyleCastExpr(Context,
+ Context->getObjCIdType(),
+ CastExpr::CK_Unknown, Cls));
// struct objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
@@ -2509,17 +2509,18 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
Context->getPointerType(SuperRep->getType()),
SourceLocation());
- SuperRep = new (Context) CStyleCastExpr(Context->getPointerType(superType),
- CastExpr::CK_Unknown, SuperRep,
- Context->getPointerType(superType),
- SourceLocation(), SourceLocation());
+ SuperRep = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(superType),
+ CastExpr::CK_Unknown, SuperRep);
} else {
// (struct objc_super) { <exprs from above> }
InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
&InitExprs[0], InitExprs.size(),
SourceLocation());
- SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superType, ILE,
- false);
+ TypeSourceInfo *superTInfo
+ = Context->getTrivialTypeSourceInfo(superType);
+ SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
+ superType, ILE, false);
// struct objc_super *
SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
Context->getPointerType(SuperRep->getType()),
@@ -2551,13 +2552,12 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
llvm::SmallVector<Expr*, 4> InitExprs;
InitExprs.push_back(
- new (Context) CStyleCastExpr(Context->getObjCIdType(),
- CastExpr::CK_Unknown,
+ NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CastExpr::CK_Unknown,
new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
Context->getObjCIdType(),
- SourceLocation()),
- Context->getObjCIdType(),
- SourceLocation(), SourceLocation())); // set the 'receiver'.
+ SourceLocation()))
+ ); // set the 'receiver'.
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
@@ -2571,9 +2571,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// To turn off a warning, type-cast to 'id'
InitExprs.push_back(
// set 'super class', using objc_getClass().
- new (Context) CStyleCastExpr(Context->getObjCIdType(),
- CastExpr::CK_Unknown,
- Cls, Context->getObjCIdType(), SourceLocation(), SourceLocation()));
+ NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CastExpr::CK_Unknown, Cls));
// struct objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
@@ -2595,16 +2594,18 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
Context->getPointerType(SuperRep->getType()),
SourceLocation());
- SuperRep = new (Context) CStyleCastExpr(Context->getPointerType(superType),
- CastExpr::CK_Unknown,
- SuperRep, Context->getPointerType(superType),
- SourceLocation(), SourceLocation());
+ SuperRep = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(superType),
+ CastExpr::CK_Unknown, SuperRep);
} else {
// (struct objc_super) { <exprs from above> }
InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
&InitExprs[0], InitExprs.size(),
SourceLocation());
- SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superType, ILE, false);
+ TypeSourceInfo *superTInfo
+ = Context->getTrivialTypeSourceInfo(superType);
+ SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
+ superType, ILE, false);
}
MsgExprs.push_back(SuperRep);
} else {
@@ -2612,10 +2613,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// Foo<Proto> *.
while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
recExpr = CE->getSubExpr();
- recExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(),
- CastExpr::CK_Unknown, recExpr,
- Context->getObjCIdType(),
- SourceLocation(), SourceLocation());
+ recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CastExpr::CK_Unknown, recExpr);
MsgExprs.push_back(recExpr);
}
}
@@ -2639,19 +2638,16 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
QualType type = ICE->getType()->isObjCQualifiedIdType()
? Context->getObjCIdType()
: ICE->getType();
- userExpr = new (Context) CStyleCastExpr(type, CastExpr::CK_Unknown,
- userExpr, type, SourceLocation(),
- SourceLocation());
+ userExpr = NoTypeInfoCStyleCastExpr(Context, type, CastExpr::CK_Unknown,
+ userExpr);
}
// Make id<P...> cast into an 'id' cast.
else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
if (CE->getType()->isObjCQualifiedIdType()) {
while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
userExpr = CE->getSubExpr();
- userExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(),
- CastExpr::CK_Unknown,
- userExpr, Context->getObjCIdType(),
- SourceLocation(), SourceLocation());
+ userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CastExpr::CK_Unknown, userExpr);
}
}
MsgExprs.push_back(userExpr);
@@ -2701,10 +2697,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// If we don't do this cast, we get the following bizarre warning/note:
// xx.m:13: warning: function called through a non-compatible type
// xx.m:13: note: if this code is reached, the program will abort
- cast = new (Context) CStyleCastExpr(Context->getPointerType(Context->VoidTy),
- CastExpr::CK_Unknown, DRE,
- Context->getPointerType(Context->VoidTy),
- SourceLocation(), SourceLocation());
+ cast = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(Context->VoidTy),
+ CastExpr::CK_Unknown, DRE);
// Now do the "normal" pointer to function cast.
QualType castType = Context->getFunctionType(returnType,
@@ -2712,9 +2707,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// If we don't have a method decl, force a variadic cast.
Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0);
castType = Context->getPointerType(castType);
- cast = new (Context) CStyleCastExpr(castType, CastExpr::CK_Unknown, cast,
- castType, SourceLocation(),
- SourceLocation());
+ cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
+ cast);
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
@@ -2734,17 +2728,16 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType,
SourceLocation());
// Need to cast objc_msgSend_stret to "void *" (see above comment).
- cast = new (Context) CStyleCastExpr(Context->getPointerType(Context->VoidTy),
- CastExpr::CK_Unknown, STDRE,
- Context->getPointerType(Context->VoidTy),
- SourceLocation(), SourceLocation());
+ cast = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(Context->VoidTy),
+ CastExpr::CK_Unknown, STDRE);
// Now do the "normal" pointer to function cast.
castType = Context->getFunctionType(returnType,
&ArgTypes[0], ArgTypes.size(),
Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0);
castType = Context->getPointerType(castType);
- cast = new (Context) CStyleCastExpr(castType, CastExpr::CK_Unknown,
- cast, castType, SourceLocation(), SourceLocation());
+ cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
+ cast);
// Don't forget the parens to enforce the proper binding.
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
@@ -2819,10 +2812,9 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
Context->getPointerType(DRE->getType()),
SourceLocation());
- CastExpr *castExpr = new (Context) CStyleCastExpr(DerefExpr->getType(),
- CastExpr::CK_Unknown,
- DerefExpr, DerefExpr->getType(),
- SourceLocation(), SourceLocation());
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
+ CastExpr::CK_Unknown,
+ DerefExpr);
ReplaceStmt(Exp, castExpr);
ProtocolExprDecls.insert(Exp->getProtocol());
// delete Exp; leak for now, see RewritePropertySetter() usage for more info.
@@ -4043,7 +4035,7 @@ std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
const char *FunName) {
// Insert declaration for the function in which block literal is used.
- if (CurFunctionDeclToDeclareForBlock)
+ if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
// Insert closures that were part of the function.
for (unsigned i = 0; i < Blocks.size(); i++) {
@@ -4204,11 +4196,9 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
- CastExpr *BlkCast = new (Context) CStyleCastExpr(PtrBlock,
- CastExpr::CK_Unknown,
- const_cast<Expr*>(BlockExp),
- PtrBlock, SourceLocation(),
- SourceLocation());
+ CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
+ CastExpr::CK_Unknown,
+ const_cast<Expr*>(BlockExp));
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
BlkCast);
@@ -4220,11 +4210,8 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
FD->getType());
- CastExpr *FunkCast = new (Context) CStyleCastExpr(PtrToFuncCastType,
- CastExpr::CK_Unknown, ME,
- PtrToFuncCastType,
- SourceLocation(),
- SourceLocation());
+ CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
+ CastExpr::CK_Unknown, ME);
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
llvm::SmallVector<Expr*, 8> BlkExprs;
@@ -4309,17 +4296,29 @@ void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
-
+ QualType QT = CE->getType();
+ const Type* TypePtr = QT->getAs<Type>();
+ if (isa<TypeOfExprType>(TypePtr)) {
+ const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
+ QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
+ std::string TypeAsString = "(";
+ TypeAsString += QT.getAsString();
+ TypeAsString += ")";
+ ReplaceText(LocStart, endBuf-startBuf+1,
+ TypeAsString.c_str(), TypeAsString.size());
+ return;
+ }
+
// advance the location to startArgList.
const char *argPtr = startBuf;
while (*argPtr++ && (argPtr < endBuf)) {
switch (*argPtr) {
- case '^':
- // Replace the '^' with '*'.
- LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf);
- ReplaceText(LocStart, 1, "*", 1);
- break;
+ case '^':
+ // Replace the '^' with '*'.
+ LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf);
+ ReplaceText(LocStart, 1, "*", 1);
+ break;
}
}
return;
@@ -4344,17 +4343,17 @@ void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
while (*argPtr++ && parenCount) {
switch (*argPtr) {
- case '^':
- // Replace the '^' with '*'.
- DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList);
- ReplaceText(DeclLoc, 1, "*", 1);
- break;
- case '(':
- parenCount++;
- break;
- case ')':
- parenCount--;
- break;
+ case '^':
+ // Replace the '^' with '*'.
+ DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList);
+ ReplaceText(DeclLoc, 1, "*", 1);
+ break;
+ case '(':
+ parenCount++;
+ break;
+ case ')':
+ parenCount--;
+ break;
}
}
return;
@@ -4390,9 +4389,9 @@ void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
while (*argPtr && parenCount) {
switch (*argPtr) {
- case '(': parenCount++; break;
- case ')': parenCount--; break;
- default: break;
+ case '(': parenCount++; break;
+ case ')': parenCount--; break;
+ default: break;
}
if (parenCount) argPtr++;
}
@@ -4557,8 +4556,13 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
ByrefType += " " + Name + ";\n";
ByrefType += "};\n";
// Insert this type in global scope. It is needed by helper function.
- assert(CurFunctionDef && "RewriteByRefVar - CurFunctionDef is null");
- SourceLocation FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
+ SourceLocation FunLocStart;
+ if (CurFunctionDef)
+ FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
+ else {
+ assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
+ FunLocStart = CurMethodDef->getLocStart();
+ }
InsertText(FunLocStart, ByrefType.c_str(), ByrefType.size());
if (Ty.isObjCGCWeak()) {
flag |= BLOCK_FIELD_IS_WEAK;
@@ -4608,12 +4612,17 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
ByrefType.c_str(), ByrefType.size());
}
else {
- SourceLocation startLoc = ND->getInit()->getLocStart();
+ SourceLocation startLoc;
+ Expr *E = ND->getInit();
+ if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
+ startLoc = ECE->getLParenLoc();
+ else
+ startLoc = E->getLocStart();
startLoc = SM->getInstantiationLoc(startLoc);
+ endBuf = SM->getCharacterData(startLoc);
+
ByrefType += " " + Name;
- ReplaceText(DeclLoc, endBuf-startBuf,
- ByrefType.c_str(), ByrefType.size());
- ByrefType = " = {(void*)";
+ ByrefType += " = {(void*)";
ByrefType += utostr(isa);
ByrefType += ", &" + Name + ", ";
ByrefType += utostr(flags);
@@ -4628,7 +4637,8 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
ByrefType += utostr(flag);
ByrefType += ", ";
}
- InsertText(startLoc, ByrefType.c_str(), ByrefType.size());
+ ReplaceText(DeclLoc, endBuf-startBuf,
+ ByrefType.c_str(), ByrefType.size());
// Complete the newly synthesized compound expression by inserting a right
// curly brace before the end of the declaration.
@@ -4719,10 +4729,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
FD = SynthBlockInitFunctionDecl(Func.c_str());
DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(),
SourceLocation());
- CastExpr *castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg,
- Context->VoidPtrTy, SourceLocation(),
- SourceLocation());
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+ CastExpr::CK_Unknown, Arg);
InitExprs.push_back(castExpr);
// Initialize the block descriptor.
@@ -4753,11 +4761,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
- Exp = new (Context) CStyleCastExpr(Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg,
- Context->VoidPtrTy,
- SourceLocation(),
- SourceLocation());
+ Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+ CastExpr::CK_Unknown, Arg);
} else {
FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
@@ -4789,9 +4794,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
NewRep = new (Context) UnaryOperator(NewRep, UnaryOperator::AddrOf,
Context->getPointerType(NewRep->getType()),
SourceLocation());
- NewRep = new (Context) CStyleCastExpr(FType, CastExpr::CK_Unknown, NewRep,
- FType, SourceLocation(),
- SourceLocation());
+ NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CastExpr::CK_Unknown,
+ NewRep);
BlockDeclRefs.clear();
BlockByRefDecls.clear();
BlockByCopyDecls.clear();
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
index c0977b5b2707..ce474d365390 100644
--- a/lib/Frontend/StmtXML.cpp
+++ b/lib/Frontend/StmtXML.cpp
@@ -89,14 +89,14 @@ namespace {
const char* pAttributeName = NAME; \
const bool optional = false; \
switch (S->FN) { \
- default: assert(0 && "unknown enum value");
+ default: assert(0 && "unknown enum value");
#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
{ \
const char* pAttributeName = NAME; \
const bool optional = true; \
switch (S->FN) { \
- default: assert(0 && "unknown enum value");
+ default: assert(0 && "unknown enum value");
#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
#define END_ENUM_XML } }
@@ -189,17 +189,17 @@ void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) {
const char* pKind;
switch (Node->getDecl()->getKind()) {
- case Decl::Function: pKind = "FunctionDecl"; break;
- case Decl::Var: pKind = "Var"; break;
- case Decl::ParmVar: pKind = "ParmVar"; break;
- case Decl::EnumConstant: pKind = "EnumConstant"; break;
- case Decl::Typedef: pKind = "Typedef"; break;
- case Decl::Record: pKind = "Record"; break;
- case Decl::Enum: pKind = "Enum"; break;
- case Decl::CXXRecord: pKind = "CXXRecord"; break;
- case Decl::ObjCInterface: pKind = "ObjCInterface"; break;
- case Decl::ObjCClass: pKind = "ObjCClass"; break;
- default: pKind = "Decl"; break;
+ case Decl::Function: pKind = "FunctionDecl"; break;
+ case Decl::Var: pKind = "Var"; break;
+ case Decl::ParmVar: pKind = "ParmVar"; break;
+ case Decl::EnumConstant: pKind = "EnumConstant"; break;
+ case Decl::Typedef: pKind = "Typedef"; break;
+ case Decl::Record: pKind = "Record"; break;
+ case Decl::Enum: pKind = "Enum"; break;
+ case Decl::CXXRecord: pKind = "CXXRecord"; break;
+ case Decl::ObjCInterface: pKind = "ObjCInterface"; break;
+ case Decl::ObjCClass: pKind = "ObjCClass"; break;
+ default: pKind = "Decl"; break;
}
Doc.addAttribute("kind", pKind);
@@ -210,10 +210,10 @@ void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) {
void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) {
DumpExpr(Node);
switch (Node->getIdentType()) {
- default: assert(0 && "unknown case");
- case PredefinedExpr::Func: Doc.addAttribute("predefined", " __func__"); break;
- case PredefinedExpr::Function: Doc.addAttribute("predefined", " __FUNCTION__"); break;
- case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break;
+ default: assert(0 && "unknown case");
+ case PredefinedExpr::Func: Doc.addAttribute("predefined", " __func__"); break;
+ case PredefinedExpr::Function: Doc.addAttribute("predefined", " __FUNCTION__"); break;
+ case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break;
}
}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index fcefd4e35822..83b4542caa25 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -428,6 +428,42 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
}
}
}
+ // Now that we have the entire fixit line, expand the tabs in it.
+ // Since we don't want to insert spaces in the middle of a word,
+ // find each word and the column it should line up with and insert
+ // spaces until they match.
+ if (!FixItInsertionLine.empty()) {
+ unsigned FixItPos = 0;
+ unsigned LinePos = 0;
+ unsigned TabExpandedCol = 0;
+ unsigned LineLength = LineEnd - LineStart;
+
+ while (FixItPos < FixItInsertionLine.size() && LinePos < LineLength) {
+ // Find the next word in the FixIt line.
+ while (FixItPos < FixItInsertionLine.size() &&
+ FixItInsertionLine[FixItPos] == ' ')
+ ++FixItPos;
+ unsigned CharDistance = FixItPos - TabExpandedCol;
+
+ // Walk forward in the source line, keeping track of
+ // the tab-expanded column.
+ for (unsigned I = 0; I < CharDistance; ++I, ++LinePos)
+ if (LinePos >= LineLength || LineStart[LinePos] != '\t')
+ ++TabExpandedCol;
+ else
+ TabExpandedCol =
+ (TabExpandedCol/DiagOpts->TabStop + 1) * DiagOpts->TabStop;
+
+ // Adjust the fixit line to match this column.
+ FixItInsertionLine.insert(FixItPos, TabExpandedCol-FixItPos, ' ');
+ FixItPos = TabExpandedCol;
+
+ // Walk to the end of the word.
+ while (FixItPos < FixItInsertionLine.size() &&
+ FixItInsertionLine[FixItPos] != ' ')
+ ++FixItPos;
+ }
+ }
}
// If the source line is too long for our terminal, select only the
diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp
index 8bd05443a7fe..be9db420d2f8 100644
--- a/lib/Frontend/TypeXML.cpp
+++ b/lib/Frontend/TypeXML.cpp
@@ -43,14 +43,14 @@ public:
const char* pAttributeName = NAME; \
const bool optional = false; \
switch (T->FN) { \
- default: assert(0 && "unknown enum value");
+ default: assert(0 && "unknown enum value");
#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
{ \
const char* pAttributeName = NAME; \
const bool optional = true; \
switch (T->FN) { \
- default: assert(0 && "unknown enum value");
+ default: assert(0 && "unknown enum value");
#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
#define END_ENUM_XML } }
diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp
index 81a5de44bf56..4bb15943bb4d 100644
--- a/lib/Index/ResolveLocation.cpp
+++ b/lib/Index/ResolveLocation.cpp
@@ -264,7 +264,7 @@ ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
return ASTLocation(D);
// Second, search through the declarations that are part of the function.
- // If we find he location there, we won't have to search through its body.
+ // If we find the location there, we won't have to search through its body.
for (DeclContext::decl_iterator
I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 0a74b26482e5..afd1ba885167 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -210,6 +210,7 @@ void Lexer::Stringify(llvm::SmallVectorImpl<char> &Str) {
}
}
+static bool isWhitespace(unsigned char c);
/// MeasureTokenLength - Relex the token at the specified location and return
/// its length in bytes in the input file. If the token needs cleaning (e.g.
@@ -231,6 +232,9 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc,
std::pair<const char *,const char *> Buffer = SM.getBufferData(LocInfo.first);
const char *StrData = Buffer.first+LocInfo.second;
+ if (isWhitespace(StrData[0]))
+ return 0;
+
// Create a lexer starting at the beginning of this token.
Lexer TheLexer(Loc, LangOpts, Buffer.first, StrData, Buffer.second);
TheLexer.SetCommentRetentionState(true);
@@ -902,8 +906,10 @@ bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr) {
// SkipBCPLComment - We have just read the // characters from input. Skip until
// we find the newline character thats terminate the comment. Then update
-/// BufferPtr and return. If we're in KeepCommentMode, this will form the token
-/// and return true.
+/// BufferPtr and return.
+///
+/// If we're in KeepCommentMode or any CommentHandler has inserted
+/// some tokens, this will store the first token and return true.
bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) {
// If BCPL comments aren't explicitly enabled for this language, emit an
// extension warning.
@@ -980,9 +986,12 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) {
} while (C != '\n' && C != '\r');
// Found but did not consume the newline.
- if (PP)
- PP->HandleComment(SourceRange(getSourceLocation(BufferPtr),
- getSourceLocation(CurPtr)));
+ if (PP && PP->HandleComment(Result,
+ SourceRange(getSourceLocation(BufferPtr),
+ getSourceLocation(CurPtr)))) {
+ BufferPtr = CurPtr;
+ return true; // A token has to be returned.
+ }
// If we are returning comments as tokens, return this comment as a token.
if (inKeepCommentMode())
@@ -1108,8 +1117,8 @@ static bool isEndOfBlockCommentWithEscapedNewLine(const char *CurPtr,
/// happen is the comment could end with an escaped newline between the */ end
/// of comment.
///
-/// If KeepCommentMode is enabled, this forms a token from the comment and
-/// returns true.
+/// If we're in KeepCommentMode or any CommentHandler has inserted
+/// some tokens, this will store the first token and return true.
bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) {
// Scan one character past where we should, looking for a '/' character. Once
// we find it, check to see if it was preceeded by a *. This common
@@ -1226,9 +1235,12 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) {
C = *CurPtr++;
}
- if (PP)
- PP->HandleComment(SourceRange(getSourceLocation(BufferPtr),
- getSourceLocation(CurPtr)));
+ if (PP && PP->HandleComment(Result,
+ SourceRange(getSourceLocation(BufferPtr),
+ getSourceLocation(CurPtr)))) {
+ BufferPtr = CurPtr;
+ return true; // A token has to be returned.
+ }
// If we are returning comments as tokens, return this comment as a token.
if (inKeepCommentMode()) {
@@ -1606,10 +1618,12 @@ LexNextToken:
// too (without going through the big switch stmt).
if (CurPtr[0] == '/' && CurPtr[1] == '/' && !inKeepCommentMode() &&
Features.BCPLComment) {
- SkipBCPLComment(Result, CurPtr+2);
+ if (SkipBCPLComment(Result, CurPtr+2))
+ return; // There is a token to return.
goto SkipIgnoredUnits;
} else if (CurPtr[0] == '/' && CurPtr[1] == '*' && !inKeepCommentMode()) {
- SkipBlockComment(Result, CurPtr+2);
+ if (SkipBlockComment(Result, CurPtr+2))
+ return; // There is a token to return.
goto SkipIgnoredUnits;
} else if (isHorizontalWhitespace(*CurPtr)) {
goto SkipHorizontalWhitespace;
@@ -1795,7 +1809,7 @@ LexNextToken:
if (Features.BCPLComment ||
getCharAndSize(CurPtr+SizeTmp, SizeTmp2) != '*') {
if (SkipBCPLComment(Result, ConsumeChar(CurPtr, SizeTmp, Result)))
- return; // KeepCommentMode
+ return; // There is a token to return.
// It is common for the tokens immediately after a // comment to be
// whitespace (indentation for the next line). Instead of going through
@@ -1806,7 +1820,7 @@ LexNextToken:
if (Char == '*') { // /**/ comment.
if (SkipBlockComment(Result, ConsumeChar(CurPtr, SizeTmp, Result)))
- return; // KeepCommentMode
+ return; // There is a token to return.
goto LexNextToken; // GCC isn't tail call eliminating.
}
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index 5cd54975055d..004e6755e5f5 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -375,7 +375,7 @@ NumericLiteralParser(const char *begin, const char *end,
continue; // Success.
case 'i':
if (PP.getLangOptions().Microsoft) {
- if (isFPConstant || isUnsigned || isLong || isLongLong) break;
+ if (isFPConstant || isLong || isLongLong) break;
// Allow i8, i16, i32, i64, and i128.
if (s + 1 != ThisTokEnd) {
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index aa807f800d3e..b0e784bcd96a 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -160,10 +160,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
CurPPLexer->LexingRawMode = true;
Token Tok;
while (1) {
- if (CurLexer)
- CurLexer->Lex(Tok);
- else
- CurPTHLexer->Lex(Tok);
+ CurLexer->Lex(Tok);
// If this is the end of the buffer, we have an error.
if (Tok.is(tok::eof)) {
@@ -405,7 +402,6 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() {
/// return null on failure. isAngled indicates whether the file reference is
/// for system #include's or not (i.e. using <> instead of "").
const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename,
- SourceLocation FilenameTokLoc,
bool isAngled,
const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir) {
@@ -432,16 +428,7 @@ const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename,
CurDir = CurDirLookup;
const FileEntry *FE =
HeaderInfo.LookupFile(Filename, isAngled, FromDir, CurDir, CurFileEnt);
- if (FE) {
- // Warn about normal quoted #include from framework headers. Since
- // framework headers are published (both public and private ones) they
- // should not do relative searches, they should do an include with the
- // framework path included.
- if (!isAngled && CurDir && FilenameTokLoc.isValid() &&
- CurDir->isFramework() && CurDir == CurDirLookup)
- Diag(FilenameTokLoc, diag::warn_pp_relative_include_from_framework);
- return FE;
- }
+ if (FE) return FE;
// Otherwise, see if this is a subframework header. If so, this is relative
// to one of the headers on the #include stack. Walk the list of the current
@@ -1082,8 +1069,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
// Search include directories.
const DirectoryLookup *CurDir;
- const FileEntry *File = LookupFile(Filename, FilenameTok.getLocation(),
- isAngled, LookupFrom, CurDir);
+ const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, CurDir);
if (File == 0) {
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 37927827a8b2..13aeb88b1db0 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -567,9 +567,7 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok,
// Search include directories.
const DirectoryLookup *CurDir;
- const FileEntry *File = PP.LookupFile(Filename,
- SourceLocation(),// produce no warnings.
- isAngled, LookupFrom, CurDir);
+ const FileEntry *File = PP.LookupFile(Filename, isAngled, LookupFrom, CurDir);
// Get the result value. Result = true means the file exists.
Result = File != 0;
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 856b3bd76d80..63b23b6d5c47 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -301,8 +301,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
// Search include directories for this file.
const DirectoryLookup *CurDir;
- const FileEntry *File = LookupFile(Filename, FilenameTok.getLocation(),
- isAngled, 0, CurDir);
+ const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir);
if (File == 0) {
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 26bb3a90dac0..5689baaac652 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -429,21 +429,17 @@ SourceLocation Preprocessor::AdvanceToTokenCharacter(SourceLocation TokStart,
return TokStart.getFileLocWithOffset(PhysOffset);
}
-/// \brief Computes the source location just past the end of the
-/// token at this source location.
-///
-/// This routine can be used to produce a source location that
-/// points just past the end of the token referenced by \p Loc, and
-/// is generally used when a diagnostic needs to point just after a
-/// token where it expected something different that it received. If
-/// the returned source location would not be meaningful (e.g., if
-/// it points into a macro), this routine returns an invalid
-/// source location.
-SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc) {
+SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc,
+ unsigned Offset) {
if (Loc.isInvalid() || !Loc.isFileID())
return SourceLocation();
unsigned Len = Lexer::MeasureTokenLength(Loc, getSourceManager(), Features);
+ if (Len > Offset)
+ Len = Len - Offset;
+ else
+ return Loc;
+
return AdvanceToTokenCharacter(Loc, Len);
}
@@ -583,11 +579,18 @@ void Preprocessor::RemoveCommentHandler(CommentHandler *Handler) {
CommentHandlers.erase(Pos);
}
-void Preprocessor::HandleComment(SourceRange Comment) {
+bool Preprocessor::HandleComment(Token &result, SourceRange Comment) {
+ bool AnyPendingTokens = false;
for (std::vector<CommentHandler *>::iterator H = CommentHandlers.begin(),
HEnd = CommentHandlers.end();
- H != HEnd; ++H)
- (*H)->HandleComment(*this, Comment);
+ H != HEnd; ++H) {
+ if ((*H)->HandleComment(*this, Comment))
+ AnyPendingTokens = true;
+ }
+ if (!AnyPendingTokens || getCommentRetentionState())
+ return false;
+ Lex(result);
+ return true;
}
CommentHandler::~CommentHandler() { }
diff --git a/lib/Makefile b/lib/Makefile
index adf9474a2aec..d499ee555a38 100755
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -8,8 +8,8 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../..
-PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis Rewrite \
- Frontend Index Driver
+PARALLEL_DIRS = Headers Runtime Basic Lex Parse AST Sema CodeGen Analysis \
+ Rewrite Frontend Index Driver
include $(LEVEL)/Makefile.common
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index f52d8b98567a..9e5f5a2ac098 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -373,11 +373,30 @@ void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos,
ProtocolLAngleLoc = LAngleLoc;
}
+void DeclSpec::SaveWrittenBuiltinSpecs() {
+ writtenBS.Sign = getTypeSpecSign();
+ writtenBS.Width = getTypeSpecWidth();
+ writtenBS.Type = getTypeSpecType();
+ // Search the list of attributes for the presence of a mode attribute.
+ writtenBS.ModeAttr = false;
+ AttributeList* attrs = getAttributes();
+ while (attrs) {
+ if (attrs->getKind() == AttributeList::AT_mode) {
+ writtenBS.ModeAttr = true;
+ break;
+ }
+ attrs = attrs->getNext();
+ }
+}
+
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
+ // Before possibly changing their values, save specs as written.
+ SaveWrittenBuiltinSpecs();
+
// Check the type specifier components first.
SourceManager &SrcMgr = PP.getSourceManager();
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 8b207fab436c..5f48897235ab 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -204,6 +204,7 @@ MinimalAction::ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtocols,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
// Allocate and add the 'TypeNameInfo' "decl".
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 90040c54bfb1..efaf8ee3270e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -983,7 +983,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
// Parse an (optional) access specifier.
AccessSpecifier Access = getAccessSpecifierIfPresent();
- if (Access)
+ if (Access != AS_none)
ConsumeToken();
// Parse the 'virtual' keyword (again!), in case it came after the
@@ -1398,15 +1398,35 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
PP.getSourceManager(),
"parsing struct/union/class body");
- // Determine whether this is a top-level (non-nested) class.
- bool TopLevelClass = ClassStack.empty() ||
- CurScope->isInCXXInlineMethodScope();
+ // Determine whether this is a non-nested class. Note that local
+ // classes are *not* considered to be nested classes.
+ bool NonNestedClass = true;
+ if (!ClassStack.empty()) {
+ for (const Scope *S = CurScope; S; S = S->getParent()) {
+ if (S->isClassScope()) {
+ // We're inside a class scope, so this is a nested class.
+ NonNestedClass = false;
+ break;
+ }
+
+ if ((S->getFlags() & Scope::FnScope)) {
+ // If we're in a function or function template declared in the
+ // body of a class, then this is a local class rather than a
+ // nested class.
+ const Scope *Parent = S->getParent();
+ if (Parent->isTemplateParamScope())
+ Parent = Parent->getParent();
+ if (Parent->isClassScope())
+ break;
+ }
+ }
+ }
// Enter a scope for the class.
ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
// Note that we are parsing a new (potentially-nested) class definition.
- ParsingClassDefinition ParsingDef(*this, TagDecl, TopLevelClass);
+ ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass);
if (TagDecl)
Actions.ActOnTagStartDefinition(CurScope, TagDecl);
@@ -1484,7 +1504,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
//
// FIXME: Only function bodies and constructor ctor-initializers are
// parsed correctly, fix the rest.
- if (TopLevelClass) {
+ if (NonNestedClass) {
// We are not inside a nested class. This class and its nested classes
// are complete and we can parse the delayed portions of method
// declarations and the lexed inline method definitions.
@@ -1666,10 +1686,10 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
/// \brief We have just started parsing the definition of a new class,
/// so push that class onto our stack of classes that is currently
/// being parsed.
-void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool TopLevelClass) {
- assert((TopLevelClass || !ClassStack.empty()) &&
+void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool NonNestedClass) {
+ assert((NonNestedClass || !ClassStack.empty()) &&
"Nested class without outer class");
- ClassStack.push(new ParsingClass(ClassDecl, TopLevelClass));
+ ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass));
}
/// \brief Deallocate the given parsed class and all of its nested
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 5e2363535320..ae85aa3a8aef 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -186,6 +186,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
categoryId, categoryLoc,
ProtocolRefs.data(),
ProtocolRefs.size(),
+ ProtocolLocs.data(),
EndProtoLoc);
ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
@@ -224,6 +225,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
superClassId, superClassLoc,
ProtocolRefs.data(), ProtocolRefs.size(),
+ ProtocolLocs.data(),
EndProtoLoc, attrList);
if (Tok.is(tok::l_brace))
@@ -1127,6 +1129,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
ProtocolRefs.data(),
ProtocolRefs.size(),
+ ProtocolLocs.data(),
EndProtoLoc, attrList);
ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
return ProtoType;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 0aecac975741..f2bc303acd69 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -29,8 +29,9 @@ class ActionCommentHandler : public CommentHandler {
public:
explicit ActionCommentHandler(Action &Actions) : Actions(Actions) { }
- virtual void HandleComment(Preprocessor &PP, SourceRange Comment) {
+ virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) {
Actions.ActOnComment(Comment);
+ return false;
}
};
diff --git a/lib/Rewrite/DeltaTree.cpp b/lib/Rewrite/DeltaTree.cpp
index 101cf93f9db9..35e888bcf595 100644
--- a/lib/Rewrite/DeltaTree.cpp
+++ b/lib/Rewrite/DeltaTree.cpp
@@ -20,7 +20,7 @@ using llvm::cast;
using llvm::dyn_cast;
/// The DeltaTree class is a multiway search tree (BTree) structure with some
-/// fancy features. B-Trees are are generally more memory and cache efficient
+/// fancy features. B-Trees are generally more memory and cache efficient
/// than binary trees, because they store multiple keys/values in each node.
///
/// DeltaTree implements a key/value mapping from FileIndex to Delta, allowing
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index fbd14502b7e5..8c4caafeac24 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -572,11 +572,11 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
break;
case Decl::ObjCImplementation:
- Kind = CXCursor_ObjCClassDefn;
+ Kind = CXCursor_ObjCImplementationDecl;
break;
case Decl::ObjCCategoryImpl:
- Kind = CXCursor_ObjCCategoryDefn;
+ Kind = CXCursor_ObjCCategoryImplDecl;
break;
default:
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index 9064de6aa019..f4cea2e88a6d 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -123,9 +123,7 @@ public:
Temporary
};
- typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
- typedef DeclsTy::const_iterator iterator;
-
+ typedef UnresolvedSetImpl::iterator iterator;
typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS);
LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
@@ -133,6 +131,7 @@ public:
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
: ResultKind(NotFound),
Paths(0),
+ NamingClass(0),
SemaRef(SemaRef),
Name(Name),
NameLoc(NameLoc),
@@ -152,6 +151,7 @@ public:
LookupResult(TemporaryToken _, const LookupResult &Other)
: ResultKind(NotFound),
Paths(0),
+ NamingClass(0),
SemaRef(Other.SemaRef),
Name(Other.Name),
NameLoc(Other.NameLoc),
@@ -224,8 +224,8 @@ public:
return Ambiguity;
}
- iterator begin() const { return Decls.begin(); }
- iterator end() const { return Decls.end(); }
+ iterator begin() const { return iterator(Decls.begin()); }
+ iterator end() const { return iterator(Decls.end()); }
/// \brief Return true if no decls were found
bool empty() const { return Decls.empty(); }
@@ -247,32 +247,57 @@ public:
return IDNS;
}
- /// \brief Add a declaration to these results. Does not test the
- /// acceptance criteria.
+ /// \brief Returns whether these results arose from performing a
+ /// lookup into a class.
+ bool isClassLookup() const {
+ return NamingClass != 0;
+ }
+
+ /// \brief Returns the 'naming class' for this lookup, i.e. the
+ /// class which was looked into to find these results.
+ ///
+ /// C++0x [class.access.base]p5:
+ /// The access to a member is affected by the class in which the
+ /// member is named. This naming class is the class in which the
+ /// member name was looked up and found. [Note: this class can be
+ /// explicit, e.g., when a qualified-id is used, or implicit,
+ /// e.g., when a class member access operator (5.2.5) is used
+ /// (including cases where an implicit "this->" is added). If both
+ /// a class member access operator and a qualified-id are used to
+ /// name the member (as in p->T::m), the class naming the member
+ /// is the class named by the nested-name-specifier of the
+ /// qualified-id (that is, T). -- end note ]
+ ///
+ /// This is set by the lookup routines when they find results in a class.
+ CXXRecordDecl *getNamingClass() const {
+ return NamingClass;
+ }
+
+ /// \brief Sets the 'naming class' for this lookup.
+ void setNamingClass(CXXRecordDecl *Record) {
+ NamingClass = Record;
+ }
+
+ /// \brief Add a declaration to these results with its natural access.
+ /// Does not test the acceptance criteria.
void addDecl(NamedDecl *D) {
- Decls.push_back(D);
+ addDecl(D, D->getAccess());
+ }
+
+ /// \brief Add a declaration to these results with the given access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D, AccessSpecifier AS) {
+ Decls.addDecl(D, AS);
ResultKind = Found;
}
/// \brief Add all the declarations from another set of lookup
/// results.
void addAllDecls(const LookupResult &Other) {
- Decls.append(Other.begin(), Other.end());
+ Decls.append(Other.Decls.begin(), Other.Decls.end());
ResultKind = Found;
}
- /// \brief Hides a set of declarations.
- template <class NamedDeclSet> void hideDecls(const NamedDeclSet &Set) {
- unsigned I = 0, N = Decls.size();
- while (I < N) {
- if (Set.count(Decls[I]))
- Decls[I] = Decls[--N];
- else
- I++;
- }
- Decls.set_size(N);
- }
-
/// \brief Determine whether no result was found because we could not
/// search into dependent base classes of the current instantiation.
bool wasNotFoundInCurrentInstantiation() const {
@@ -319,13 +344,13 @@ public:
NamedDecl *getFoundDecl() const {
assert(getResultKind() == Found
&& "getFoundDecl called on non-unique result");
- return Decls[0]->getUnderlyingDecl();
+ return (*begin())->getUnderlyingDecl();
}
/// Fetches a representative decl. Useful for lazy diagnostics.
NamedDecl *getRepresentativeDecl() const {
assert(!Decls.empty() && "cannot get representative of empty set");
- return Decls[0];
+ return *begin();
}
/// \brief Asks if the result is a single tag decl.
@@ -403,7 +428,7 @@ public:
/// sugared.
class Filter {
LookupResult &Results;
- unsigned I;
+ LookupResult::iterator I;
bool Changed;
#ifndef NDEBUG
bool CalledDone;
@@ -411,7 +436,7 @@ public:
friend class LookupResult;
Filter(LookupResult &Results)
- : Results(Results), I(0), Changed(false)
+ : Results(Results), I(Results.begin()), Changed(false)
#ifndef NDEBUG
, CalledDone(false)
#endif
@@ -426,23 +451,30 @@ public:
#endif
bool hasNext() const {
- return I != Results.Decls.size();
+ return I != Results.end();
}
NamedDecl *next() {
- assert(I < Results.Decls.size() && "next() called on empty filter");
- return Results.Decls[I++];
+ assert(I != Results.end() && "next() called on empty filter");
+ return *I++;
}
/// Erase the last element returned from this iterator.
void erase() {
- Results.Decls[--I] = Results.Decls.back();
- Results.Decls.pop_back();
+ Results.Decls.erase(--I);
Changed = true;
}
+ /// Replaces the current entry with the given one, preserving the
+ /// access bits.
void replace(NamedDecl *D) {
- Results.Decls[I-1] = D;
+ Results.Decls.replace(I-1, D);
+ Changed = true;
+ }
+
+ /// Replaces the current entry with the given one.
+ void replace(NamedDecl *D, AccessSpecifier AS) {
+ Results.Decls.replace(I-1, D, AS);
Changed = true;
}
@@ -466,6 +498,8 @@ private:
void diagnose() {
if (isAmbiguous())
SemaRef.DiagnoseAmbiguousLookup(*this);
+ else if (isClassLookup() && SemaRef.getLangOptions().AccessControl)
+ SemaRef.CheckAccess(*this);
}
void setAmbiguous(AmbiguityKind AK) {
@@ -482,7 +516,7 @@ private:
assert(ResultKind != Found || Decls.size() == 1);
assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
(Decls.size() == 1 &&
- isa<FunctionTemplateDecl>(Decls[0]->getUnderlyingDecl())));
+ isa<FunctionTemplateDecl>((*begin())->getUnderlyingDecl())));
assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved());
assert(ResultKind != Ambiguous || Decls.size() > 1 ||
(Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects));
@@ -492,8 +526,7 @@ private:
}
bool sanityCheckUnresolved() const {
- for (DeclsTy::const_iterator I = Decls.begin(), E = Decls.end();
- I != E; ++I)
+ for (iterator I = begin(), E = end(); I != E; ++I)
if (isa<UnresolvedUsingValueDecl>(*I))
return true;
return false;
@@ -504,8 +537,9 @@ private:
// Results.
LookupResultKind ResultKind;
AmbiguityKind Ambiguity; // ill-defined unless ambiguous
- DeclsTy Decls;
+ UnresolvedSet<8> Decls;
CXXBasePaths *Paths;
+ CXXRecordDecl *NamingClass;
// Parameters.
Sema &SemaRef;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index fab729299936..06e9e3ae9e64 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1291,6 +1291,17 @@ public:
ObjCContainerDecl* IDecl,
bool IncompleteImpl = false);
+ /// DiagnoseUnimplementedProperties - This routine warns on those properties
+ /// which must be implemented by this implementation.
+ void DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl *CDecl,
+ const llvm::DenseSet<Selector>& InsMap);
+
+ /// CollectImmediateProperties - This routine collects all properties in
+ /// the class and its conforming protocols; but not those it its super class.
+ void CollectImmediateProperties(ObjCContainerDecl *CDecl,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap);
+
/// AtomicPropertySetterGetterRules - This routine enforces the rule (via
/// warning) when atomic property has one but not the other user-declared
/// setter or getter.
@@ -1651,6 +1662,11 @@ public:
virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
TypeTy *Ty, SourceLocation RParenLoc,
ExprArg Op);
+ OwningExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *Ty,
+ SourceLocation RParenLoc,
+ ExprArg Op);
+
virtual bool TypeIsVectorType(TypeTy *Ty) {
return GetTypeFromParser(Ty)->isVectorType();
}
@@ -1658,13 +1674,18 @@ public:
OwningExprResult MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg ME);
OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
SourceLocation RParenLoc, ExprArg E,
- QualType Ty);
+ TypeSourceInfo *TInfo);
virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
TypeTy *Ty,
SourceLocation RParenLoc,
ExprArg Op);
+ OwningExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ ExprArg InitExpr);
+
virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
MultiExprArg InitList,
SourceLocation RParenLoc);
@@ -1920,6 +1941,13 @@ public:
ExprArg E,
SourceLocation RParenLoc);
+ OwningExprResult BuildCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ TypeSourceInfo *Ty,
+ ExprArg E,
+ SourceRange AngleBrackets,
+ SourceRange Parens);
+
/// ActOnCXXTypeid - Parse typeid( something ).
virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
SourceLocation LParenLoc, bool isType,
@@ -2033,7 +2061,6 @@ public:
bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
bool isUnknownSpecialization(const CXXScopeSpec &SS);
- bool isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS);
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
@@ -2334,6 +2361,9 @@ public:
CXXBasePaths &Paths,
bool NoPrivileges = false);
+ void CheckAccess(const LookupResult &R);
+ bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access);
+
bool CheckBaseClassAccess(QualType Derived, QualType Base,
unsigned InaccessibleBaseID,
CXXBasePaths& Paths, SourceLocation AccessLoc,
@@ -3153,13 +3183,17 @@ public:
/// relevant to this particular scope).
LocalInstantiationScope *Outer;
+ /// \brief Whether we have already exited this scope.
+ bool Exited;
+
// This class is non-copyable
LocalInstantiationScope(const LocalInstantiationScope &);
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
public:
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
- : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) {
+ : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
+ Exited(false) {
if (!CombineWithOuterScope)
SemaRef.CurrentInstantiationScope = this;
else
@@ -3168,7 +3202,15 @@ public:
}
~LocalInstantiationScope() {
+ if (!Exited)
+ SemaRef.CurrentInstantiationScope = Outer;
+ }
+
+ /// \brief Exit this local instantiation scope early.
+ void Exit() {
SemaRef.CurrentInstantiationScope = Outer;
+ LocalDecls.clear();
+ Exited = true;
}
Decl *getInstantiationOf(const Decl *D) {
@@ -3215,7 +3257,16 @@ public:
/// but have not yet been performed.
std::deque<PendingImplicitInstantiation> PendingImplicitInstantiations;
- void PerformPendingImplicitInstantiations();
+ /// \brief The queue of implicit template instantiations that are required
+ /// and must be performed within the current local scope.
+ ///
+ /// This queue is only used for member functions of local classes in
+ /// templates, which must be instantiated in the same scope as their
+ /// enclosing function, so that they can reference function-local
+ /// types, static variables, enumerators, etc.
+ std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
+
+ void PerformPendingImplicitInstantiations(bool LocalOnly = false);
TypeSourceInfo *SubstType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &TemplateArgs,
@@ -3300,6 +3351,7 @@ public:
SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
@@ -3317,6 +3369,7 @@ public:
SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
const DeclPtrTy *ProtoRefNames, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
@@ -3327,6 +3380,7 @@ public:
SourceLocation CategoryLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc);
virtual DeclPtrTy ActOnStartClassImplementation(
@@ -3373,14 +3427,13 @@ public:
ObjCMethodDecl *MethodDecl,
bool IsInstance);
- void MergeProtocolPropertiesIntoClass(Decl *CDecl,
- DeclPtrTy MergeProtocols);
+ void CompareProperties(Decl *CDecl, DeclPtrTy MergeProtocols);
void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
ObjCInterfaceDecl *ID);
- void MergeOneProtocolPropertiesIntoClass(Decl *CDecl,
- ObjCProtocolDecl *PDecl);
+ void MatchOneProtocolPropertiesInClass(Decl *CDecl,
+ ObjCProtocolDecl *PDecl);
virtual void ActOnAtEnd(SourceRange AtEnd,
DeclPtrTy classDecl,
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index b7cc37b6c9a7..51f9e300ef90 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
@@ -137,3 +138,101 @@ bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
return false;
}
+
+/// Diagnose the path which caused the given declaration to become
+/// inaccessible.
+static void DiagnoseAccessPath(Sema &S, const LookupResult &R, NamedDecl *D,
+ AccessSpecifier Access) {
+ // Easy case: the decl's natural access determined its path access.
+ if (Access == D->getAccess() || D->getAccess() == AS_private) {
+ S.Diag(D->getLocation(), diag::note_access_natural)
+ << (unsigned) (Access == AS_protected);
+ return;
+ }
+
+ // TODO: flesh this out
+ S.Diag(D->getLocation(), diag::note_access_constrained_by_path)
+ << (unsigned) (Access == AS_protected);
+}
+
+/// Checks access to the given declaration in the current context.
+///
+/// \param R the means via which the access was made; must have a naming
+/// class set
+/// \param D the declaration accessed
+/// \param Access the best access along any inheritance path from the
+/// naming class to the declaration. AS_none means the path is impossible
+bool Sema::CheckAccess(const LookupResult &R, NamedDecl *D,
+ AccessSpecifier Access) {
+ assert(R.getNamingClass() && "performing access check without naming class");
+
+ // If the access path is public, it's accessible everywhere.
+ if (Access == AS_public)
+ return false;
+
+ // Otherwise, derive the current class context.
+ DeclContext *DC = CurContext;
+ while (isa<CXXRecordDecl>(DC) &&
+ cast<CXXRecordDecl>(DC)->isAnonymousStructOrUnion())
+ DC = DC->getParent();
+
+ CXXRecordDecl *CurRecord;
+ if (isa<CXXRecordDecl>(DC))
+ CurRecord = cast<CXXRecordDecl>(DC);
+ else if (isa<CXXMethodDecl>(DC))
+ CurRecord = cast<CXXMethodDecl>(DC)->getParent();
+ else {
+ Diag(R.getNameLoc(), diag::err_access_outside_class)
+ << (Access == AS_protected);
+ DiagnoseAccessPath(*this, R, D, Access);
+ return true;
+ }
+
+ CXXRecordDecl *NamingClass = R.getNamingClass();
+ while (NamingClass->isAnonymousStructOrUnion())
+ // This should be guaranteed by the fact that the decl has
+ // non-public access. If not, we should make it guaranteed!
+ NamingClass = cast<CXXRecordDecl>(NamingClass);
+
+ // White-list accesses from within the declaring class.
+ if (Access != AS_none &&
+ CurRecord->getCanonicalDecl() == NamingClass->getCanonicalDecl())
+ return false;
+
+ // Protected access.
+ if (Access == AS_protected) {
+ // FIXME: implement [class.protected]p1
+ if (CurRecord->isDerivedFrom(NamingClass))
+ return false;
+
+ // FIXME: dependent classes
+ }
+
+ // FIXME: friends
+
+ // Okay, it's a bad access, reject it.
+
+
+ CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext());
+
+ if (Access == AS_protected) {
+ Diag(R.getNameLoc(), diag::err_access_protected)
+ << Context.getTypeDeclType(DeclaringClass)
+ << Context.getTypeDeclType(CurRecord);
+ DiagnoseAccessPath(*this, R, D, Access);
+ return true;
+ }
+
+ assert(Access == AS_private || Access == AS_none);
+ Diag(R.getNameLoc(), diag::err_access_private)
+ << Context.getTypeDeclType(DeclaringClass)
+ << Context.getTypeDeclType(CurRecord);
+ DiagnoseAccessPath(*this, R, D, Access);
+ return true;
+}
+
+/// Checks access to all the declarations in the given result set.
+void Sema::CheckAccess(const LookupResult &R) {
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ CheckAccess(R, *I, I.getAccess());
+}
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index f924bd3bb121..57c4f9bc2a27 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -116,11 +116,26 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
SourceLocation RAngleBracketLoc,
SourceLocation LParenLoc, ExprArg E,
SourceLocation RParenLoc) {
+
+ TypeSourceInfo *DestTInfo;
+ QualType DestType = GetTypeFromParser(Ty, &DestTInfo);
+ if (!DestTInfo)
+ DestTInfo = Context.getTrivialTypeSourceInfo(DestType, SourceLocation());
+
+ return BuildCXXNamedCast(OpLoc, Kind, DestTInfo, move(E),
+ SourceRange(LAngleBracketLoc, RAngleBracketLoc),
+ SourceRange(LParenLoc, RParenLoc));
+}
+
+Action::OwningExprResult
+Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ TypeSourceInfo *DestTInfo, ExprArg E,
+ SourceRange AngleBrackets, SourceRange Parens) {
Expr *Ex = E.takeAs<Expr>();
- // FIXME: Preserve type source info.
- QualType DestType = GetTypeFromParser(Ty);
- SourceRange OpRange(OpLoc, RParenLoc);
- SourceRange DestRange(LAngleBracketLoc, RAngleBracketLoc);
+ QualType DestType = DestTInfo->getType();
+
+ SourceRange OpRange(OpLoc, Parens.getEnd());
+ SourceRange DestRange = AngleBrackets;
// If the type is dependent, we won't do the semantic analysis now.
// FIXME: should we check this in a more fine-grained manner?
@@ -133,14 +148,14 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
if (!TypeDependent)
CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
return Owned(new (Context) CXXConstCastExpr(DestType.getNonReferenceType(),
- Ex, DestType, OpLoc));
+ Ex, DestTInfo, OpLoc));
case tok::kw_dynamic_cast: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
if (!TypeDependent)
CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind);
return Owned(new (Context)CXXDynamicCastExpr(DestType.getNonReferenceType(),
- Kind, Ex, DestType, OpLoc));
+ Kind, Ex, DestTInfo, OpLoc));
}
case tok::kw_reinterpret_cast: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
@@ -148,7 +163,7 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
return Owned(new (Context) CXXReinterpretCastExpr(
DestType.getNonReferenceType(),
- Kind, Ex, DestType, OpLoc));
+ Kind, Ex, DestTInfo, OpLoc));
}
case tok::kw_static_cast: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
@@ -169,7 +184,7 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
}
return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(),
- Kind, Ex, DestType, OpLoc));
+ Kind, Ex, DestTInfo, OpLoc));
}
}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 8594583ec3ef..7a0b6252064d 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -30,9 +30,9 @@ getCurrentInstantiationOf(ASTContext &Context, DeclContext *CurContext,
if (T.isNull())
return 0;
- T = Context.getCanonicalType(T);
+ T = Context.getCanonicalType(T).getUnqualifiedType();
- for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {
+ for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getLookupParent()) {
// If we've hit a namespace or the global scope, then the
// nested-name-specifier can't refer to the current instantiation.
if (Ctx->isFileContext())
@@ -210,28 +210,6 @@ bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) {
return getCurrentInstantiationOf(NNS) == 0;
}
-/// \brief Determine whether the given scope specifier refers to a
-/// current instantiation that has any dependent base clases.
-///
-/// This check is typically used when we've performed lookup into the
-/// current instantiation of a template, but that lookup failed. When
-/// there are dependent bases present, however, the lookup needs to be
-/// delayed until template instantiation time.
-bool Sema::isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS) {
- if (!SS.isSet())
- return false;
-
- NestedNameSpecifier *NNS = (NestedNameSpecifier*)SS.getScopeRep();
- if (!NNS->isDependent())
- return false;
-
- CXXRecordDecl *CurrentInstantiation = getCurrentInstantiationOf(NNS);
- if (!CurrentInstantiation)
- return false;
-
- return CurrentInstantiation->hasAnyDependentBases();
-}
-
/// \brief If the given nested name specifier refers to the current
/// instantiation, return the declaration that corresponds to that
/// current instantiation (C++0x [temp.dep.type]p1).
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 5f124e457223..6ff8b1d75371 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -13,14 +13,22 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/PathSensitive/AnalysisContext.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/STLExtras.h"
#include <limits>
+#include <queue>
using namespace clang;
/// getLocationOfStringLiteralByte - Return a source location that points to the
@@ -2029,3 +2037,522 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T) {
return;
}
+// MarkLive - Mark all the blocks reachable from e as live. Returns the total
+// number of blocks just marked live.
+static unsigned MarkLive(CFGBlock *e, llvm::BitVector &live) {
+ unsigned count = 0;
+ std::queue<CFGBlock*> workq;
+ // Prep work queue
+ live.set(e->getBlockID());
+ ++count;
+ workq.push(e);
+ // Solve
+ while (!workq.empty()) {
+ CFGBlock *item = workq.front();
+ workq.pop();
+ for (CFGBlock::succ_iterator I=item->succ_begin(),
+ E=item->succ_end();
+ I != E;
+ ++I) {
+ if ((*I) && !live[(*I)->getBlockID()]) {
+ live.set((*I)->getBlockID());
+ ++count;
+ workq.push(*I);
+ }
+ }
+ }
+ return count;
+}
+
+static SourceLocation GetUnreachableLoc(CFGBlock &b, SourceRange &R1,
+ SourceRange &R2) {
+ Stmt *S;
+ unsigned sn = 0;
+ R1 = R2 = SourceRange();
+
+ top:
+ if (sn < b.size())
+ S = b[sn].getStmt();
+ else if (b.getTerminator())
+ S = b.getTerminator();
+ else
+ return SourceLocation();
+
+ switch (S->getStmtClass()) {
+ case Expr::BinaryOperatorClass: {
+ BinaryOperator *BO = cast<BinaryOperator>(S);
+ if (BO->getOpcode() == BinaryOperator::Comma) {
+ if (sn+1 < b.size())
+ return b[sn+1].getStmt()->getLocStart();
+ CFGBlock *n = &b;
+ while (1) {
+ if (n->getTerminator())
+ return n->getTerminator()->getLocStart();
+ if (n->succ_size() != 1)
+ return SourceLocation();
+ n = n[0].succ_begin()[0];
+ if (n->pred_size() != 1)
+ return SourceLocation();
+ if (!n->empty())
+ return n[0][0].getStmt()->getLocStart();
+ }
+ }
+ R1 = BO->getLHS()->getSourceRange();
+ R2 = BO->getRHS()->getSourceRange();
+ return BO->getOperatorLoc();
+ }
+ case Expr::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(S);
+ R1 = UO->getSubExpr()->getSourceRange();
+ return UO->getOperatorLoc();
+ }
+ case Expr::CompoundAssignOperatorClass: {
+ const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
+ R1 = CAO->getLHS()->getSourceRange();
+ R2 = CAO->getRHS()->getSourceRange();
+ return CAO->getOperatorLoc();
+ }
+ case Expr::ConditionalOperatorClass: {
+ const ConditionalOperator *CO = cast<ConditionalOperator>(S);
+ return CO->getQuestionLoc();
+ }
+ case Expr::MemberExprClass: {
+ const MemberExpr *ME = cast<MemberExpr>(S);
+ R1 = ME->getSourceRange();
+ return ME->getMemberLoc();
+ }
+ case Expr::ArraySubscriptExprClass: {
+ const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
+ R1 = ASE->getLHS()->getSourceRange();
+ R2 = ASE->getRHS()->getSourceRange();
+ return ASE->getRBracketLoc();
+ }
+ case Expr::CStyleCastExprClass: {
+ const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
+ R1 = CSC->getSubExpr()->getSourceRange();
+ return CSC->getLParenLoc();
+ }
+ case Expr::CXXFunctionalCastExprClass: {
+ const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
+ R1 = CE->getSubExpr()->getSourceRange();
+ return CE->getTypeBeginLoc();
+ }
+ case Expr::ImplicitCastExprClass:
+ ++sn;
+ goto top;
+ case Stmt::CXXTryStmtClass: {
+ return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
+ }
+ default: ;
+ }
+ R1 = S->getSourceRange();
+ return S->getLocStart();
+}
+
+static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
+ SourceManager &SM) {
+ std::queue<CFGBlock*> workq;
+ // Prep work queue
+ workq.push(e);
+ SourceRange R1, R2;
+ SourceLocation top = GetUnreachableLoc(*e, R1, R2);
+ bool FromMainFile = false;
+ bool FromSystemHeader = false;
+ bool TopValid = false;
+ if (top.isValid()) {
+ FromMainFile = SM.isFromMainFile(top);
+ FromSystemHeader = SM.isInSystemHeader(top);
+ TopValid = true;
+ }
+ // Solve
+ while (!workq.empty()) {
+ CFGBlock *item = workq.front();
+ workq.pop();
+ SourceLocation c = GetUnreachableLoc(*item, R1, R2);
+ if (c.isValid()
+ && (!TopValid
+ || (SM.isFromMainFile(c) && !FromMainFile)
+ || (FromSystemHeader && !SM.isInSystemHeader(c))
+ || SM.isBeforeInTranslationUnit(c, top))) {
+ top = c;
+ FromMainFile = SM.isFromMainFile(top);
+ FromSystemHeader = SM.isInSystemHeader(top);
+ }
+ live.set(item->getBlockID());
+ for (CFGBlock::succ_iterator I=item->succ_begin(),
+ E=item->succ_end();
+ I != E;
+ ++I) {
+ if ((*I) && !live[(*I)->getBlockID()]) {
+ live.set((*I)->getBlockID());
+ workq.push(*I);
+ }
+ }
+ }
+ return top;
+}
+
+static int LineCmp(const void *p1, const void *p2) {
+ SourceLocation *Line1 = (SourceLocation *)p1;
+ SourceLocation *Line2 = (SourceLocation *)p2;
+ return !(*Line1 < *Line2);
+}
+
+namespace {
+ struct ErrLoc {
+ SourceLocation Loc;
+ SourceRange R1;
+ SourceRange R2;
+ ErrLoc(SourceLocation l, SourceRange r1, SourceRange r2)
+ : Loc(l), R1(r1), R2(r2) { }
+ };
+}
+
+/// CheckUnreachable - Check for unreachable code.
+void Sema::CheckUnreachable(AnalysisContext &AC) {
+ unsigned count;
+ // We avoid checking when there are errors, as the CFG won't faithfully match
+ // the user's code.
+ if (getDiagnostics().hasErrorOccurred())
+ return;
+ if (Diags.getDiagnosticLevel(diag::warn_unreachable) == Diagnostic::Ignored)
+ return;
+
+ CFG *cfg = AC.getCFG();
+ if (cfg == 0)
+ return;
+
+ llvm::BitVector live(cfg->getNumBlockIDs());
+ // Mark all live things first.
+ count = MarkLive(&cfg->getEntry(), live);
+
+ if (count == cfg->getNumBlockIDs())
+ // If there are no dead blocks, we're done.
+ return;
+
+ SourceRange R1, R2;
+
+ llvm::SmallVector<ErrLoc, 24> lines;
+ bool AddEHEdges = AC.getAddEHEdges();
+ // First, give warnings for blocks with no predecessors, as they
+ // can't be part of a loop.
+ for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+ CFGBlock &b = **I;
+ if (!live[b.getBlockID()]) {
+ if (b.pred_begin() == b.pred_end()) {
+ if (!AddEHEdges && b.getTerminator()
+ && isa<CXXTryStmt>(b.getTerminator())) {
+ // When not adding EH edges from calls, catch clauses
+ // can otherwise seem dead. Avoid noting them as dead.
+ count += MarkLive(&b, live);
+ continue;
+ }
+ SourceLocation c = GetUnreachableLoc(b, R1, R2);
+ if (!c.isValid()) {
+ // Blocks without a location can't produce a warning, so don't mark
+ // reachable blocks from here as live.
+ live.set(b.getBlockID());
+ ++count;
+ continue;
+ }
+ lines.push_back(ErrLoc(c, R1, R2));
+ // Avoid excessive errors by marking everything reachable from here
+ count += MarkLive(&b, live);
+ }
+ }
+ }
+
+ if (count < cfg->getNumBlockIDs()) {
+ // And then give warnings for the tops of loops.
+ for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+ CFGBlock &b = **I;
+ if (!live[b.getBlockID()])
+ // Avoid excessive errors by marking everything reachable from here
+ lines.push_back(ErrLoc(MarkLiveTop(&b, live, Context.getSourceManager()), SourceRange(), SourceRange()));
+ }
+ }
+
+ llvm::array_pod_sort(lines.begin(), lines.end(), LineCmp);
+ for (llvm::SmallVector<ErrLoc, 24>::iterator I = lines.begin(),
+ E = lines.end();
+ I != E;
+ ++I)
+ if (I->Loc.isValid())
+ Diag(I->Loc, diag::warn_unreachable) << I->R1 << I->R2;
+}
+
+/// CheckFallThrough - Check that we don't fall off the end of a
+/// Statement that should return a value.
+///
+/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
+/// MaybeFallThrough iff we might or might not fall off the end,
+/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
+/// return. We assume NeverFallThrough iff we never fall off the end of the
+/// statement but we may return. We assume that functions not marked noreturn
+/// will return.
+Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) {
+ CFG *cfg = AC.getCFG();
+ if (cfg == 0)
+ // FIXME: This should be NeverFallThrough
+ return NeverFallThroughOrReturn;
+
+ // The CFG leaves in dead things, and we don't want the dead code paths to
+ // confuse us, so we mark all live things first.
+ std::queue<CFGBlock*> workq;
+ llvm::BitVector live(cfg->getNumBlockIDs());
+ unsigned count = MarkLive(&cfg->getEntry(), live);
+
+ bool AddEHEdges = AC.getAddEHEdges();
+ if (!AddEHEdges && count != cfg->getNumBlockIDs())
+ // When there are things remaining dead, and we didn't add EH edges
+ // from CallExprs to the catch clauses, we have to go back and
+ // mark them as live.
+ for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+ CFGBlock &b = **I;
+ if (!live[b.getBlockID()]) {
+ if (b.pred_begin() == b.pred_end()) {
+ if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
+ // When not adding EH edges from calls, catch clauses
+ // can otherwise seem dead. Avoid noting them as dead.
+ count += MarkLive(&b, live);
+ continue;
+ }
+ }
+ }
+
+ // Now we know what is live, we check the live precessors of the exit block
+ // and look for fall through paths, being careful to ignore normal returns,
+ // and exceptional paths.
+ bool HasLiveReturn = false;
+ bool HasFakeEdge = false;
+ bool HasPlainEdge = false;
+ bool HasAbnormalEdge = false;
+ for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
+ E = cfg->getExit().pred_end();
+ I != E;
+ ++I) {
+ CFGBlock& B = **I;
+ if (!live[B.getBlockID()])
+ continue;
+ if (B.size() == 0) {
+ if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
+ HasAbnormalEdge = true;
+ continue;
+ }
+
+ // A labeled empty statement, or the entry block...
+ HasPlainEdge = true;
+ continue;
+ }
+ Stmt *S = B[B.size()-1];
+ if (isa<ReturnStmt>(S)) {
+ HasLiveReturn = true;
+ continue;
+ }
+ if (isa<ObjCAtThrowStmt>(S)) {
+ HasFakeEdge = true;
+ continue;
+ }
+ if (isa<CXXThrowExpr>(S)) {
+ HasFakeEdge = true;
+ continue;
+ }
+ if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
+ if (AS->isMSAsm()) {
+ HasFakeEdge = true;
+ HasLiveReturn = true;
+ continue;
+ }
+ }
+ if (isa<CXXTryStmt>(S)) {
+ HasAbnormalEdge = true;
+ continue;
+ }
+
+ bool NoReturnEdge = false;
+ if (CallExpr *C = dyn_cast<CallExpr>(S)) {
+ if (B.succ_begin()[0] != &cfg->getExit()) {
+ HasAbnormalEdge = true;
+ continue;
+ }
+ Expr *CEE = C->getCallee()->IgnoreParenCasts();
+ if (CEE->getType().getNoReturnAttr()) {
+ NoReturnEdge = true;
+ HasFakeEdge = true;
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
+ ValueDecl *VD = DRE->getDecl();
+ if (VD->hasAttr<NoReturnAttr>()) {
+ NoReturnEdge = true;
+ HasFakeEdge = true;
+ }
+ }
+ }
+ // FIXME: Add noreturn message sends.
+ if (NoReturnEdge == false)
+ HasPlainEdge = true;
+ }
+ if (!HasPlainEdge) {
+ if (HasLiveReturn)
+ return NeverFallThrough;
+ return NeverFallThroughOrReturn;
+ }
+ if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
+ return MaybeFallThrough;
+ // This says AlwaysFallThrough for calls to functions that are not marked
+ // noreturn, that don't return. If people would like this warning to be more
+ // accurate, such functions should be marked as noreturn.
+ return AlwaysFallThrough;
+}
+
+/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// function that should return a value. Check that we don't fall off the end
+/// of a noreturn function. We assume that functions and blocks not marked
+/// noreturn will return.
+void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body,
+ AnalysisContext &AC) {
+ // FIXME: Would be nice if we had a better way to control cascading errors,
+ // but for now, avoid them. The problem is that when Parse sees:
+ // int foo() { return a; }
+ // The return is eaten and the Sema code sees just:
+ // int foo() { }
+ // which this code would then warn about.
+ if (getDiagnostics().hasErrorOccurred())
+ return;
+
+ bool ReturnsVoid = false;
+ bool HasNoReturn = false;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // If the result type of the function is a dependent type, we don't know
+ // whether it will be void or not, so don't
+ if (FD->getResultType()->isDependentType())
+ return;
+ if (FD->getResultType()->isVoidType())
+ ReturnsVoid = true;
+ if (FD->hasAttr<NoReturnAttr>())
+ HasNoReturn = true;
+ } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (MD->getResultType()->isVoidType())
+ ReturnsVoid = true;
+ if (MD->hasAttr<NoReturnAttr>())
+ HasNoReturn = true;
+ }
+
+ // Short circuit for compilation speed.
+ if ((Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
+ == Diagnostic::Ignored || ReturnsVoid)
+ && (Diags.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
+ == Diagnostic::Ignored || !HasNoReturn)
+ && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
+ == Diagnostic::Ignored || !ReturnsVoid))
+ return;
+ // FIXME: Function try block
+ if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+ switch (CheckFallThrough(AC)) {
+ case MaybeFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(),diag::warn_maybe_falloff_nonvoid_function);
+ break;
+ case AlwaysFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
+ break;
+ case NeverFallThroughOrReturn:
+ if (ReturnsVoid && !HasNoReturn)
+ Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
+ break;
+ case NeverFallThrough:
+ break;
+ }
+ }
+}
+
+/// CheckFallThroughForBlock - Check that we don't fall off the end of a block
+/// that should return a value. Check that we don't fall off the end of a
+/// noreturn block. We assume that functions and blocks not marked noreturn
+/// will return.
+void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body,
+ AnalysisContext &AC) {
+ // FIXME: Would be nice if we had a better way to control cascading errors,
+ // but for now, avoid them. The problem is that when Parse sees:
+ // int foo() { return a; }
+ // The return is eaten and the Sema code sees just:
+ // int foo() { }
+ // which this code would then warn about.
+ if (getDiagnostics().hasErrorOccurred())
+ return;
+ bool ReturnsVoid = false;
+ bool HasNoReturn = false;
+ if (const FunctionType *FT =BlockTy->getPointeeType()->getAs<FunctionType>()){
+ if (FT->getResultType()->isVoidType())
+ ReturnsVoid = true;
+ if (FT->getNoReturnAttr())
+ HasNoReturn = true;
+ }
+
+ // Short circuit for compilation speed.
+ if (ReturnsVoid
+ && !HasNoReturn
+ && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
+ == Diagnostic::Ignored || !ReturnsVoid))
+ return;
+ // FIXME: Funtion try block
+ if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+ switch (CheckFallThrough(AC)) {
+ case MaybeFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(), diag::err_maybe_falloff_nonvoid_block);
+ break;
+ case AlwaysFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
+ break;
+ case NeverFallThroughOrReturn:
+ if (ReturnsVoid)
+ Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
+ break;
+ case NeverFallThrough:
+ break;
+ }
+ }
+}
+
+/// CheckParmsForFunctionDef - Check that the parameters of the given
+/// function are appropriate for the definition of a function. This
+/// takes care of any checks that cannot be performed on the
+/// declaration itself, e.g., that the types of each of the function
+/// parameters are complete.
+bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
+ bool HasInvalidParm = false;
+ for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
+ ParmVarDecl *Param = FD->getParamDecl(p);
+
+ // C99 6.7.5.3p4: the parameters in a parameter type list in a
+ // function declarator that is part of a function definition of
+ // that function shall not have incomplete type.
+ //
+ // This is also C++ [dcl.fct]p6.
+ if (!Param->isInvalidDecl() &&
+ RequireCompleteType(Param->getLocation(), Param->getType(),
+ diag::err_typecheck_decl_incomplete_type)) {
+ Param->setInvalidDecl();
+ HasInvalidParm = true;
+ }
+
+ // C99 6.9.1p5: If the declarator includes a parameter type list, the
+ // declaration of each parameter shall include an identifier.
+ if (Param->getIdentifier() == 0 &&
+ !Param->isImplicit() &&
+ !getLangOptions().CPlusPlus)
+ Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+ }
+
+ return HasInvalidParm;
+}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index a4cda014aae2..fcd419bb10fb 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2234,30 +2234,36 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
// FIXME: What if we're calling a pseudo-destructor?
// FIXME: What if we're calling a member function?
+ typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
+ llvm::SmallVector<ResultCandidate, 8> Results;
+
Expr *NakedFn = Fn->IgnoreParenCasts();
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
/*PartialOverloading=*/ true);
else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
- if (FDecl)
- AddOverloadCandidate(FDecl, Args, NumArgs, CandidateSet,
- false, false, /*PartialOverloading*/ true);
+ if (FDecl) {
+ if (!FDecl->getType()->getAs<FunctionProtoType>())
+ Results.push_back(ResultCandidate(FDecl));
+ else
+ AddOverloadCandidate(FDecl, Args, NumArgs, CandidateSet,
+ false, false, /*PartialOverloading*/ true);
+ }
}
- // Sort the overload candidate set by placing the best overloads first.
- std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
- IsBetterOverloadCandidate(*this));
+ if (!CandidateSet.empty()) {
+ // Sort the overload candidate set by placing the best overloads first.
+ std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
+ IsBetterOverloadCandidate(*this));
- // Add the remaining viable overload candidates as code-completion reslults.
- typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
- llvm::SmallVector<ResultCandidate, 8> Results;
-
- for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
- CandEnd = CandidateSet.end();
- Cand != CandEnd; ++Cand) {
- if (Cand->Viable)
- Results.push_back(ResultCandidate(Cand->Function));
+ // Add the remaining viable overload candidates as code-completion reslults.
+ for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+ CandEnd = CandidateSet.end();
+ Cand != CandEnd; ++Cand) {
+ if (Cand->Viable)
+ Results.push_back(ResultCandidate(Cand->Function));
+ }
}
if (Results.empty())
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 0ccb8f2b1d5f..fbe02894ace5 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -18,13 +18,10 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/Analysis/CFG.h"
#include "clang/AST/CXXInheritance.h"
-#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/AST/StmtObjC.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Template.h"
@@ -34,13 +31,10 @@
// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include <algorithm>
#include <cstring>
#include <functional>
-#include <queue>
using namespace clang;
/// getDeclName - Return a pretty name for the specified decl if possible, or
@@ -1305,382 +1299,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// Keep a chain of previous declarations.
New->setPreviousDeclaration(Old);
-}
-
-static void MarkLive(CFGBlock *e, llvm::BitVector &live) {
- std::queue<CFGBlock*> workq;
- // Prep work queue
- workq.push(e);
- // Solve
- while (!workq.empty()) {
- CFGBlock *item = workq.front();
- workq.pop();
- live.set(item->getBlockID());
- for (CFGBlock::succ_iterator I=item->succ_begin(),
- E=item->succ_end();
- I != E;
- ++I) {
- if ((*I) && !live[(*I)->getBlockID()]) {
- live.set((*I)->getBlockID());
- workq.push(*I);
- }
- }
- }
-}
-
-static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
- SourceManager &SM) {
- std::queue<CFGBlock*> workq;
- // Prep work queue
- workq.push(e);
- SourceLocation top;
- if (!e->empty())
- top = e[0][0].getStmt()->getLocStart();
- bool FromMainFile = false;
- bool FromSystemHeader = false;
- bool TopValid = false;
- if (top.isValid()) {
- FromMainFile = SM.isFromMainFile(top);
- FromSystemHeader = SM.isInSystemHeader(top);
- TopValid = true;
- }
- // Solve
- while (!workq.empty()) {
- CFGBlock *item = workq.front();
- workq.pop();
- SourceLocation c;
- if (!item->empty())
- c = item[0][0].getStmt()->getLocStart();
- else if (item->getTerminator())
- c = item->getTerminator()->getLocStart();
- if (c.isValid()
- && (!TopValid
- || (SM.isFromMainFile(c) && !FromMainFile)
- || (FromSystemHeader && !SM.isInSystemHeader(c))
- || SM.isBeforeInTranslationUnit(c, top))) {
- top = c;
- FromMainFile = SM.isFromMainFile(top);
- FromSystemHeader = SM.isInSystemHeader(top);
- }
- live.set(item->getBlockID());
- for (CFGBlock::succ_iterator I=item->succ_begin(),
- E=item->succ_end();
- I != E;
- ++I) {
- if ((*I) && !live[(*I)->getBlockID()]) {
- live.set((*I)->getBlockID());
- workq.push(*I);
- }
- }
- }
- return top;
-}
-namespace {
-class LineCmp {
- SourceManager &SM;
-public:
- LineCmp(SourceManager &sm) : SM(sm) {
- }
- bool operator () (SourceLocation l1, SourceLocation l2) {
- return l1 < l2;
- }
-};
-}
-
-/// CheckUnreachable - Check for unreachable code.
-void Sema::CheckUnreachable(AnalysisContext &AC) {
- // We avoid checking when there are errors, as the CFG won't faithfully match
- // the user's code.
- if (getDiagnostics().hasErrorOccurred())
- return;
- if (Diags.getDiagnosticLevel(diag::warn_unreachable) == Diagnostic::Ignored)
- return;
-
- CFG *cfg = AC.getCFG();
- if (cfg == 0)
- return;
-
- llvm::BitVector live(cfg->getNumBlockIDs());
- // Mark all live things first.
- MarkLive(&cfg->getEntry(), live);
-
- llvm::SmallVector<SourceLocation, 24> lines;
- // First, give warnings for blocks with no predecessors, as they
- // can't be part of a loop.
- for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
- CFGBlock &b = **I;
- if (!live[b.getBlockID()]) {
- if (b.pred_begin() == b.pred_end()) {
- if (!b.empty())
- lines.push_back(b[0].getStmt()->getLocStart());
- else if (b.getTerminator())
- lines.push_back(b.getTerminator()->getLocStart());
- // Avoid excessive errors by marking everything reachable from here
- MarkLive(&b, live);
- }
- }
- }
-
- // And then give warnings for the tops of loops.
- for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
- CFGBlock &b = **I;
- if (!live[b.getBlockID()])
- // Avoid excessive errors by marking everything reachable from here
- lines.push_back(MarkLiveTop(&b, live, Context.getSourceManager()));
- }
-
- std::sort(lines.begin(), lines.end(), LineCmp(Context.getSourceManager()));
- for (llvm::SmallVector<SourceLocation, 24>::iterator I = lines.begin(),
- E = lines.end();
- I != E;
- ++I)
- if (I->isValid())
- Diag(*I, diag::warn_unreachable);
-}
-
-/// CheckFallThrough - Check that we don't fall off the end of a
-/// Statement that should return a value.
-///
-/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
-/// MaybeFallThrough iff we might or might not fall off the end,
-/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
-/// return. We assume NeverFallThrough iff we never fall off the end of the
-/// statement but we may return. We assume that functions not marked noreturn
-/// will return.
-Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) {
- CFG *cfg = AC.getCFG();
- if (cfg == 0)
- // FIXME: This should be NeverFallThrough
- return NeverFallThroughOrReturn;
-
- // The CFG leaves in dead things, and we don't want to dead code paths to
- // confuse us, so we mark all live things first.
- std::queue<CFGBlock*> workq;
- llvm::BitVector live(cfg->getNumBlockIDs());
- MarkLive(&cfg->getEntry(), live);
-
- // Now we know what is live, we check the live precessors of the exit block
- // and look for fall through paths, being careful to ignore normal returns,
- // and exceptional paths.
- bool HasLiveReturn = false;
- bool HasFakeEdge = false;
- bool HasPlainEdge = false;
- for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
- E = cfg->getExit().pred_end();
- I != E;
- ++I) {
- CFGBlock& B = **I;
- if (!live[B.getBlockID()])
- continue;
- if (B.size() == 0) {
- // A labeled empty statement, or the entry block...
- HasPlainEdge = true;
- continue;
- }
- Stmt *S = B[B.size()-1];
- if (isa<ReturnStmt>(S)) {
- HasLiveReturn = true;
- continue;
- }
- if (isa<ObjCAtThrowStmt>(S)) {
- HasFakeEdge = true;
- continue;
- }
- if (isa<CXXThrowExpr>(S)) {
- HasFakeEdge = true;
- continue;
- }
- if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
- if (AS->isMSAsm()) {
- HasFakeEdge = true;
- HasLiveReturn = true;
- continue;
- }
- }
-
- bool NoReturnEdge = false;
- if (CallExpr *C = dyn_cast<CallExpr>(S)) {
- Expr *CEE = C->getCallee()->IgnoreParenCasts();
- if (CEE->getType().getNoReturnAttr()) {
- NoReturnEdge = true;
- HasFakeEdge = true;
- } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
- ValueDecl *VD = DRE->getDecl();
- if (VD->hasAttr<NoReturnAttr>()) {
- NoReturnEdge = true;
- HasFakeEdge = true;
- }
- }
- }
- // FIXME: Add noreturn message sends.
- if (NoReturnEdge == false)
- HasPlainEdge = true;
- }
- if (!HasPlainEdge) {
- if (HasLiveReturn)
- return NeverFallThrough;
- return NeverFallThroughOrReturn;
- }
- if (HasFakeEdge || HasLiveReturn)
- return MaybeFallThrough;
- // This says AlwaysFallThrough for calls to functions that are not marked
- // noreturn, that don't return. If people would like this warning to be more
- // accurate, such functions should be marked as noreturn.
- return AlwaysFallThrough;
-}
-
-/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
-/// function that should return a value. Check that we don't fall off the end
-/// of a noreturn function. We assume that functions and blocks not marked
-/// noreturn will return.
-void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body,
- AnalysisContext &AC) {
- // FIXME: Would be nice if we had a better way to control cascading errors,
- // but for now, avoid them. The problem is that when Parse sees:
- // int foo() { return a; }
- // The return is eaten and the Sema code sees just:
- // int foo() { }
- // which this code would then warn about.
- if (getDiagnostics().hasErrorOccurred())
- return;
-
- bool ReturnsVoid = false;
- bool HasNoReturn = false;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- // If the result type of the function is a dependent type, we don't know
- // whether it will be void or not, so don't
- if (FD->getResultType()->isDependentType())
- return;
- if (FD->getResultType()->isVoidType())
- ReturnsVoid = true;
- if (FD->hasAttr<NoReturnAttr>())
- HasNoReturn = true;
- } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- if (MD->getResultType()->isVoidType())
- ReturnsVoid = true;
- if (MD->hasAttr<NoReturnAttr>())
- HasNoReturn = true;
- }
-
- // Short circuit for compilation speed.
- if ((Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
- == Diagnostic::Ignored || ReturnsVoid)
- && (Diags.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
- == Diagnostic::Ignored || !HasNoReturn)
- && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
- == Diagnostic::Ignored || !ReturnsVoid))
- return;
- // FIXME: Function try block
- if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
- switch (CheckFallThrough(AC)) {
- case MaybeFallThrough:
- if (HasNoReturn)
- Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
- else if (!ReturnsVoid)
- Diag(Compound->getRBracLoc(),diag::warn_maybe_falloff_nonvoid_function);
- break;
- case AlwaysFallThrough:
- if (HasNoReturn)
- Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
- else if (!ReturnsVoid)
- Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
- break;
- case NeverFallThroughOrReturn:
- if (ReturnsVoid && !HasNoReturn)
- Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
- break;
- case NeverFallThrough:
- break;
- }
- }
-}
-
-/// CheckFallThroughForBlock - Check that we don't fall off the end of a block
-/// that should return a value. Check that we don't fall off the end of a
-/// noreturn block. We assume that functions and blocks not marked noreturn
-/// will return.
-void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body,
- AnalysisContext &AC) {
- // FIXME: Would be nice if we had a better way to control cascading errors,
- // but for now, avoid them. The problem is that when Parse sees:
- // int foo() { return a; }
- // The return is eaten and the Sema code sees just:
- // int foo() { }
- // which this code would then warn about.
- if (getDiagnostics().hasErrorOccurred())
- return;
- bool ReturnsVoid = false;
- bool HasNoReturn = false;
- if (const FunctionType *FT =BlockTy->getPointeeType()->getAs<FunctionType>()){
- if (FT->getResultType()->isVoidType())
- ReturnsVoid = true;
- if (FT->getNoReturnAttr())
- HasNoReturn = true;
- }
-
- // Short circuit for compilation speed.
- if (ReturnsVoid
- && !HasNoReturn
- && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
- == Diagnostic::Ignored || !ReturnsVoid))
- return;
- // FIXME: Funtion try block
- if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
- switch (CheckFallThrough(AC)) {
- case MaybeFallThrough:
- if (HasNoReturn)
- Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
- else if (!ReturnsVoid)
- Diag(Compound->getRBracLoc(), diag::err_maybe_falloff_nonvoid_block);
- break;
- case AlwaysFallThrough:
- if (HasNoReturn)
- Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
- else if (!ReturnsVoid)
- Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
- break;
- case NeverFallThroughOrReturn:
- if (ReturnsVoid)
- Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
- break;
- case NeverFallThrough:
- break;
- }
- }
-}
-
-/// CheckParmsForFunctionDef - Check that the parameters of the given
-/// function are appropriate for the definition of a function. This
-/// takes care of any checks that cannot be performed on the
-/// declaration itself, e.g., that the types of each of the function
-/// parameters are complete.
-bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
- bool HasInvalidParm = false;
- for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
- ParmVarDecl *Param = FD->getParamDecl(p);
-
- // C99 6.7.5.3p4: the parameters in a parameter type list in a
- // function declarator that is part of a function definition of
- // that function shall not have incomplete type.
- //
- // This is also C++ [dcl.fct]p6.
- if (!Param->isInvalidDecl() &&
- RequireCompleteType(Param->getLocation(), Param->getType(),
- diag::err_typecheck_decl_incomplete_type)) {
- Param->setInvalidDecl();
- HasInvalidParm = true;
- }
-
- // C99 6.9.1p5: If the declarator includes a parameter type list, the
- // declaration of each parameter shall include an identifier.
- if (Param->getIdentifier() == 0 &&
- !Param->isImplicit() &&
- !getLangOptions().CPlusPlus)
- Diag(Param->getLocation(), diag::err_parameter_name_omitted);
- }
-
- return HasInvalidParm;
+ // Inherit access appropriately.
+ New->setAccess(Old->getAccess());
}
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
@@ -1773,6 +1394,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
/// \return true if this is a forbidden redeclaration
static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
Scope *S,
+ DeclContext *Owner,
DeclarationName Name,
SourceLocation NameLoc,
unsigned diagnostic) {
@@ -1785,6 +1407,11 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
// Pick a representative declaration.
NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
+ if (PrevDecl && Owner->isRecord()) {
+ RecordDecl *Record = cast<RecordDecl>(Owner);
+ if (!SemaRef.isDeclInScope(PrevDecl, Record, S))
+ return false;
+ }
SemaRef.Diag(NameLoc, diagnostic) << Name;
SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
@@ -1819,7 +1446,7 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
FEnd = AnonRecord->field_end();
F != FEnd; ++F) {
if ((*F)->getDeclName()) {
- if (CheckAnonMemberRedeclaration(*this, S, (*F)->getDeclName(),
+ if (CheckAnonMemberRedeclaration(*this, S, Owner, (*F)->getDeclName(),
(*F)->getLocation(), diagKind)) {
// C++ [class.union]p2:
// The names of the members of an anonymous union shall be
@@ -3243,7 +2870,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Synthesize a parameter for each argument type.
for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
AE = FT->arg_type_end(); AI != AE; ++AI) {
- ParmVarDecl *Param = ParmVarDecl::Create(Context, DC,
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD,
SourceLocation(), 0,
*AI, /*TInfo=*/0,
VarDecl::None, 0);
@@ -3322,6 +2949,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
+ // Fake up an access specifier if it's supposed to be a class member.
+ if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
+ NewFD->setAccess(AS_public);
+
// An out-of-line member function declaration must also be a
// definition (C++ [dcl.meaning]p1).
// Note that this is not the case for explicit specializations of
@@ -3332,7 +2963,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
- } else if (!Redeclaration) {
+ } else if (!Redeclaration &&
+ !(isFriend && CurContext->isDependentContext())) {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
// was no such member function declared (C++ [class.mfct]p2,
@@ -4236,8 +3868,13 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
QualType T = adjustParameterType(parmDeclType);
+ // Temporarily put parameter variables in the translation unit, not
+ // the enclosing context. This prevents them from accidentally
+ // looking like class members in C++.
+ DeclContext *DC = Context.getTranslationUnitDecl();
+
ParmVarDecl *New
- = ParmVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), II,
+ = ParmVarDecl::Create(Context, DC, D.getIdentifierLoc(), II,
T, TInfo, StorageClass, 0);
if (D.isInvalidType())
@@ -4476,7 +4113,9 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
Decl *dcl = D.getAs<Decl>();
Stmt *Body = BodyArg.takeAs<Stmt>();
- AnalysisContext AC(dcl);
+ // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
+ // explosion for destrutors that can result and the compile time hit.
+ AnalysisContext AC(dcl, false);
FunctionDecl *FD = 0;
FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
if (FunTmpl)
@@ -6064,7 +5703,8 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
// Verify that there isn't already something declared with this name in this
// scope.
- NamedDecl *PrevDecl = LookupSingleName(S, Id, LookupOrdinaryName);
+ NamedDecl *PrevDecl = LookupSingleName(S, Id, LookupOrdinaryName,
+ ForRedeclaration);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
@@ -6092,8 +5732,10 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
IdLoc, Id, Owned(Val));
// Register this decl in the current scope stack.
- if (New)
+ if (New) {
+ New->setAccess(TheEnumDecl->getAccess());
PushOnScopeChains(New, S);
+ }
return DeclPtrTy::make(New);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a81a04e45e18..9ec95f3d170d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1062,8 +1062,23 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
if (!TyD) {
if (R.isAmbiguous()) return true;
+ if (SS.isSet() && isDependentScopeSpecifier(SS)) {
+ bool NotUnknownSpecialization = false;
+ DeclContext *DC = computeDeclContext(SS, false);
+ if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC))
+ NotUnknownSpecialization = !Record->hasAnyDependentBases();
+
+ if (!NotUnknownSpecialization) {
+ // When the scope specifier can refer to a member of an unknown
+ // specialization, we take it as a type name.
+ BaseType = CheckTypenameType((NestedNameSpecifier *)SS.getScopeRep(),
+ *MemberOrBase, SS.getRange());
+ R.clear();
+ }
+ }
+
// If no results were found, try to correct typos.
- if (R.empty() &&
+ if (R.empty() && BaseType.isNull() &&
CorrectTypo(R, S, &SS, ClassDecl) && R.isSingleResult()) {
if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) {
@@ -1106,20 +1121,22 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
}
}
- if (!TyD) {
+ if (!TyD && BaseType.isNull()) {
Diag(IdLoc, diag::err_mem_init_not_member_or_class)
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
return true;
}
}
- BaseType = Context.getTypeDeclType(TyD);
- if (SS.isSet()) {
- NestedNameSpecifier *Qualifier =
- static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ if (BaseType.isNull()) {
+ BaseType = Context.getTypeDeclType(TyD);
+ if (SS.isSet()) {
+ NestedNameSpecifier *Qualifier =
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep());
- // FIXME: preserve source range information
- BaseType = Context.getQualifiedNameType(Qualifier, BaseType);
+ // FIXME: preserve source range information
+ BaseType = Context.getQualifiedNameType(Qualifier, BaseType);
+ }
}
}
@@ -4470,9 +4487,9 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
OverloadCandidateSet CandidateSet;
- const UnresolvedSet *Conversions
+ const UnresolvedSetImpl *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
@@ -5594,26 +5611,24 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType();
- QualType CNewTy = Context.getCanonicalType(NewTy);
- QualType COldTy = Context.getCanonicalType(OldTy);
-
- if (CNewTy == COldTy &&
- CNewTy.getLocalCVRQualifiers() == COldTy.getLocalCVRQualifiers())
+ if (Context.hasSameType(NewTy, OldTy))
return false;
// Check if the return types are covariant
QualType NewClassTy, OldClassTy;
/// Both types must be pointers or references to classes.
- if (PointerType *NewPT = dyn_cast<PointerType>(NewTy)) {
- if (PointerType *OldPT = dyn_cast<PointerType>(OldTy)) {
+ if (const PointerType *NewPT = NewTy->getAs<PointerType>()) {
+ if (const PointerType *OldPT = OldTy->getAs<PointerType>()) {
NewClassTy = NewPT->getPointeeType();
OldClassTy = OldPT->getPointeeType();
}
- } else if (ReferenceType *NewRT = dyn_cast<ReferenceType>(NewTy)) {
- if (ReferenceType *OldRT = dyn_cast<ReferenceType>(OldTy)) {
- NewClassTy = NewRT->getPointeeType();
- OldClassTy = OldRT->getPointeeType();
+ } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) {
+ if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) {
+ if (NewRT->getTypeClass() == OldRT->getTypeClass()) {
+ NewClassTy = NewRT->getPointeeType();
+ OldClassTy = OldRT->getPointeeType();
+ }
}
}
@@ -5661,7 +5676,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
}
// The qualifiers of the return types must be the same.
- if (CNewTy.getLocalCVRQualifiers() != COldTy.getLocalCVRQualifiers()) {
+ if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) {
Diag(New->getLocation(),
diag::err_covariant_return_type_different_qualifications)
<< New->getDeclName() << NewTy << OldTy;
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index f2fc1f4f56df..1b07d19882e0 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -81,6 +81,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc, AttributeList *AttrList) {
assert(ClassName && "Missing class identifier");
@@ -201,7 +202,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
/// Check then save referenced protocols.
if (NumProtoRefs) {
IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
- Context);
+ ProtoLocs, Context);
IDecl->setLocEnd(EndProtoLoc);
}
@@ -279,6 +280,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
SourceLocation ProtocolLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
// FIXME: Deal with AttrList.
@@ -312,7 +314,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
ProcessDeclAttributeList(TUScope, PDecl, AttrList);
if (NumProtoRefs) {
/// Check then save referenced protocols.
- PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context);
+ PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+ ProtoLocs, Context);
PDecl->setLocEnd(EndProtoLoc);
}
@@ -432,17 +435,17 @@ void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
}
}
-/// MergeOneProtocolPropertiesIntoClass - This routine goes thru the list
-/// of properties declared in a protocol and adds them to the list
-/// of properties for current class/category if it is not there already.
+/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
+/// of properties declared in a protocol and compares their attribute against
+/// the same property declared in the class or category.
void
-Sema::MergeOneProtocolPropertiesIntoClass(Decl *CDecl,
+Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
ObjCProtocolDecl *PDecl) {
ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
if (!IDecl) {
// Category
ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
- assert (CatDecl && "MergeOneProtocolPropertiesIntoClass");
+ assert (CatDecl && "MatchOneProtocolPropertiesInClass");
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
E = PDecl->prop_end(); P != E; ++P) {
ObjCPropertyDecl *Pr = (*P);
@@ -471,35 +474,35 @@ Sema::MergeOneProtocolPropertiesIntoClass(Decl *CDecl,
}
}
-/// MergeProtocolPropertiesIntoClass - This routine merges properties
-/// declared in 'MergeItsProtocols' objects (which can be a class or an
-/// inherited protocol into the list of properties for class/category 'CDecl'
+/// CompareProperties - This routine compares properties
+/// declared in 'ClassOrProtocol' objects (which can be a class or an
+/// inherited protocol with the list of properties for class/category 'CDecl'
///
-void Sema::MergeProtocolPropertiesIntoClass(Decl *CDecl,
- DeclPtrTy MergeItsProtocols) {
- Decl *ClassDecl = MergeItsProtocols.getAs<Decl>();
+void Sema::CompareProperties(Decl *CDecl,
+ DeclPtrTy ClassOrProtocol) {
+ Decl *ClassDecl = ClassOrProtocol.getAs<Decl>();
ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
if (!IDecl) {
// Category
ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
- assert (CatDecl && "MergeProtocolPropertiesIntoClass");
+ assert (CatDecl && "CompareProperties");
if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
E = MDecl->protocol_end(); P != E; ++P)
- // Merge properties of category (*P) into IDECL's
- MergeOneProtocolPropertiesIntoClass(CatDecl, *P);
+ // Match properties of category with those of protocol (*P)
+ MatchOneProtocolPropertiesInClass(CatDecl, *P);
- // Go thru the list of protocols for this category and recursively merge
- // their properties into this class as well.
+ // Go thru the list of protocols for this category and recursively match
+ // their properties with those in the category.
for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
E = CatDecl->protocol_end(); P != E; ++P)
- MergeProtocolPropertiesIntoClass(CatDecl, DeclPtrTy::make(*P));
+ CompareProperties(CatDecl, DeclPtrTy::make(*P));
} else {
ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
E = MD->protocol_end(); P != E; ++P)
- MergeOneProtocolPropertiesIntoClass(CatDecl, *P);
+ MatchOneProtocolPropertiesInClass(CatDecl, *P);
}
return;
}
@@ -507,19 +510,19 @@ void Sema::MergeProtocolPropertiesIntoClass(Decl *CDecl,
if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
E = MDecl->protocol_end(); P != E; ++P)
- // Merge properties of class (*P) into IDECL's
- MergeOneProtocolPropertiesIntoClass(IDecl, *P);
+ // Match properties of class IDecl with those of protocol (*P).
+ MatchOneProtocolPropertiesInClass(IDecl, *P);
- // Go thru the list of protocols for this class and recursively merge
- // their properties into this class as well.
+ // Go thru the list of protocols for this class and recursively match
+ // their properties with those declared in the class.
for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
E = IDecl->protocol_end(); P != E; ++P)
- MergeProtocolPropertiesIntoClass(IDecl, DeclPtrTy::make(*P));
+ CompareProperties(IDecl, DeclPtrTy::make(*P));
} else {
ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
E = MD->protocol_end(); P != E; ++P)
- MergeOneProtocolPropertiesIntoClass(IDecl, *P);
+ MatchOneProtocolPropertiesInClass(IDecl, *P);
}
}
@@ -559,6 +562,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
unsigned NumElts,
AttributeList *attrList) {
llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols;
+ llvm::SmallVector<SourceLocation, 8> ProtoLocs;
for (unsigned i = 0; i != NumElts; ++i) {
IdentifierInfo *Ident = IdentList[i].first;
@@ -571,11 +575,13 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
if (attrList)
ProcessDeclAttributeList(TUScope, PDecl, attrList);
Protocols.push_back(PDecl);
+ ProtoLocs.push_back(IdentList[i].second);
}
ObjCForwardProtocolDecl *PDecl =
ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc,
- &Protocols[0], Protocols.size());
+ Protocols.data(), Protocols.size(),
+ ProtoLocs.data());
CurContext->addDecl(PDecl);
CheckObjCDeclScope(PDecl);
return DeclPtrTy::make(PDecl);
@@ -588,9 +594,11 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
SourceLocation CategoryLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc) {
ObjCCategoryDecl *CDecl =
- ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, CategoryName);
+ ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc,
+ CategoryLoc, CategoryName);
// FIXME: PushOnScopeChains?
CurContext->addDecl(CDecl);
@@ -623,12 +631,12 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
if (NumProtoRefs) {
CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
- Context);
- CDecl->setLocEnd(EndProtoLoc);
+ ProtoLocs, Context);
// Protocols in the class extension belong to the class.
if (!CDecl->getIdentifier())
IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs,
- NumProtoRefs,Context);
+ NumProtoRefs, ProtoLocs,
+ Context);
}
CheckObjCDeclScope(CDecl);
@@ -650,6 +658,7 @@ Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation(
// Category @implementation with no corresponding @interface.
// Create and install one.
CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(),
+ SourceLocation(), SourceLocation(),
CatName);
CatIDecl->setClassInterface(IDecl);
CatIDecl->insertNextClassCategory();
@@ -1077,6 +1086,92 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
}
}
+/// CollectImmediateProperties - This routine collects all properties in
+/// the class and its conforming protocols; but not those it its super class.
+void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+ if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+ E = IDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ PropMap[Prop->getIdentifier()] = Prop;
+ }
+ // scan through class's protocols.
+ for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
+ E = IDecl->protocol_end(); PI != E; ++PI)
+ CollectImmediateProperties((*PI), PropMap);
+ }
+ if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
+ E = CATDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ PropMap[Prop->getIdentifier()] = Prop;
+ }
+ // scan through class's protocols.
+ for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
+ E = CATDecl->protocol_end(); PI != E; ++PI)
+ CollectImmediateProperties((*PI), PropMap);
+ }
+ else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
+ if (!PropEntry)
+ PropEntry = Prop;
+ }
+ // scan through protocol's protocols.
+ for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+ E = PDecl->protocol_end(); PI != E; ++PI)
+ CollectImmediateProperties((*PI), PropMap);
+ }
+}
+
+void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl *CDecl,
+ const llvm::DenseSet<Selector>& InsMap) {
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
+ CollectImmediateProperties(CDecl, PropMap);
+ if (PropMap.empty())
+ return;
+
+ llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
+ for (ObjCImplDecl::propimpl_iterator
+ I = IMPDecl->propimpl_begin(),
+ EI = IMPDecl->propimpl_end(); I != EI; ++I)
+ PropImplMap.insert((*I)->getPropertyDecl());
+
+ for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
+ P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = P->second;
+ // Is there a matching propery synthesize/dynamic?
+ if (Prop->isInvalidDecl() ||
+ Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
+ PropImplMap.count(Prop))
+ continue;
+
+ if (!InsMap.count(Prop->getGetterName())) {
+ Diag(Prop->getLocation(),
+ isa<ObjCCategoryDecl>(CDecl) ?
+ diag::warn_setter_getter_impl_required_in_category :
+ diag::warn_setter_getter_impl_required)
+ << Prop->getDeclName() << Prop->getGetterName();
+ Diag(IMPDecl->getLocation(),
+ diag::note_property_impl_required);
+ }
+
+ if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
+ Diag(Prop->getLocation(),
+ isa<ObjCCategoryDecl>(CDecl) ?
+ diag::warn_setter_getter_impl_required_in_category :
+ diag::warn_setter_getter_impl_required)
+ << Prop->getDeclName() << Prop->getSetterName();
+ Diag(IMPDecl->getLocation(),
+ diag::note_property_impl_required);
+ }
+ }
+}
+
void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
ObjCContainerDecl* CDecl,
bool IncompleteImpl) {
@@ -1091,39 +1186,8 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
// an implementation or 2) there is a @synthesize/@dynamic implementation
// of the property in the @implementation.
if (isa<ObjCInterfaceDecl>(CDecl))
- for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(),
- E = CDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = (*P);
- if (Prop->isInvalidDecl())
- continue;
- ObjCPropertyImplDecl *PI = 0;
- // Is there a matching propery synthesize/dynamic?
- for (ObjCImplDecl::propimpl_iterator
- I = IMPDecl->propimpl_begin(),
- EI = IMPDecl->propimpl_end(); I != EI; ++I)
- if ((*I)->getPropertyDecl() == Prop) {
- PI = (*I);
- break;
- }
- if (PI)
- continue;
- if (!InsMap.count(Prop->getGetterName())) {
- Diag(Prop->getLocation(),
- diag::warn_setter_getter_impl_required)
- << Prop->getDeclName() << Prop->getGetterName();
- Diag(IMPDecl->getLocation(),
- diag::note_property_impl_required);
- }
-
- if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
- Diag(Prop->getLocation(),
- diag::warn_setter_getter_impl_required)
- << Prop->getDeclName() << Prop->getSetterName();
- Diag(IMPDecl->getLocation(),
- diag::note_property_impl_required);
- }
- }
-
+ DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);
+
llvm::DenseSet<Selector> ClsMap;
for (ObjCImplementationDecl::classmeth_iterator
I = IMPDecl->classmeth_begin(),
@@ -1163,7 +1227,18 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
E = C->protocol_end(); PI != E; ++PI)
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
InsMap, ClsMap, C->getClassInterface());
- }
+ // Report unimplemented properties in the category as well.
+ // When reporting on missing setter/getters, do not report when
+ // setter/getter is implemented in category's primary class
+ // implementation.
+ if (ObjCInterfaceDecl *ID = C->getClassInterface())
+ if (ObjCImplDecl *IMP = ID->getImplementation()) {
+ for (ObjCImplementationDecl::instmeth_iterator
+ I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
+ InsMap.insert((*I)->getSelector());
+ }
+ DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);
+ }
} else
assert(false && "invalid ObjCContainerDecl type.");
}
@@ -1694,14 +1769,14 @@ void Sema::ActOnAtEnd(SourceRange AtEnd,
// Compares properties declared in this class to those of its
// super class.
ComparePropertiesInBaseAndSuper(I);
- MergeProtocolPropertiesIntoClass(I, DeclPtrTy::make(I));
+ CompareProperties(I, DeclPtrTy::make(I));
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
// Categories are used to extend the class by declaring new methods.
// By the same token, they are also used to add new properties. No
// need to compare the added property to those in the class.
- // Merge protocol properties into category
- MergeProtocolPropertiesIntoClass(C, DeclPtrTy::make(C));
+ // Compare protocol properties with those in category
+ CompareProperties(C, DeclPtrTy::make(C));
if (C->getIdentifier() == 0)
DiagnoseClassExtensionDupMethods(C, C->getClassInterface());
}
@@ -2111,7 +2186,8 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
assert(DC && "ClassDecl is not a DeclContext");
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
FD.D.getIdentifierLoc(),
- FD.D.getIdentifier(), T);
+ FD.D.getIdentifier(),
+ AtLoc, T);
DeclContext::lookup_result Found = DC->lookup(PDecl->getDeclName());
if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) {
Diag(PDecl->getLocation(), diag::err_duplicate_property);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 034accd1c4e1..50976f7b704b 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3082,15 +3082,9 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
return ExprError();
- if (Getter || Setter) {
+ if (Getter) {
QualType PType;
-
- if (Getter)
- PType = Getter->getResultType();
- else
- // Get the expression type from Setter's incoming parameter.
- PType = (*(Setter->param_end() -1))->getType();
- // FIXME: we must check that the setter has property type.
+ PType = Getter->getResultType();
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
Setter, MemberLoc, BaseExpr));
}
@@ -3663,11 +3657,21 @@ Action::OwningExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc, ExprArg InitExpr) {
assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
-
- QualType literalType = GetTypeFromParser(Ty);
-
// FIXME: put back this assert when initializers are worked out.
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
+
+ TypeSourceInfo *TInfo;
+ QualType literalType = GetTypeFromParser(Ty, &TInfo);
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(literalType);
+
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, move(InitExpr));
+}
+
+Action::OwningExprResult
+Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc, ExprArg InitExpr) {
+ QualType literalType = TInfo->getType();
Expr *literalExpr = static_cast<Expr*>(InitExpr.get());
if (literalType->isArrayType()) {
@@ -3703,8 +3707,7 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
Result.release();
- // FIXME: Store the TInfo to preserve type information better.
- return Owned(new (Context) CompoundLiteralExpr(LParenLoc, literalType,
+ return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
literalExpr, isFileScope));
}
@@ -3906,26 +3909,38 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
Action::OwningExprResult
Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc, ExprArg Op) {
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
-
assert((Ty != 0) && (Op.get() != 0) &&
"ActOnCastExpr(): missing type or expr");
- Expr *castExpr = (Expr *)Op.get();
- //FIXME: Preserve type source info.
- QualType castType = GetTypeFromParser(Ty);
+ TypeSourceInfo *castTInfo;
+ QualType castType = GetTypeFromParser(Ty, &castTInfo);
+ if (!castTInfo)
+ castTInfo = Context.getTrivialTypeSourceInfo(castType);
// If the Expr being casted is a ParenListExpr, handle it specially.
+ Expr *castExpr = (Expr *)Op.get();
if (isa<ParenListExpr>(castExpr))
- return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),castType);
+ return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),
+ castTInfo);
+
+ return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, move(Op));
+}
+
+Action::OwningExprResult
+Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
+ SourceLocation RParenLoc, ExprArg Op) {
+ Expr *castExpr = static_cast<Expr*>(Op.get());
+
CXXMethodDecl *Method = 0;
- if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr,
+ CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+ if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
Kind, Method))
return ExprError();
if (Method) {
- OwningExprResult CastArg = BuildCXXCastArgument(LParenLoc, castType, Kind,
- Method, move(Op));
+ // FIXME: preserve type source info here
+ OwningExprResult CastArg = BuildCXXCastArgument(LParenLoc, Ty->getType(),
+ Kind, Method, move(Op));
if (CastArg.isInvalid())
return ExprError();
@@ -3935,8 +3950,8 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty,
Op.release();
}
- return Owned(new (Context) CStyleCastExpr(castType.getNonReferenceType(),
- Kind, castExpr, castType,
+ return Owned(new (Context) CStyleCastExpr(Ty->getType().getNonReferenceType(),
+ Kind, castExpr, Ty,
LParenLoc, RParenLoc));
}
@@ -3961,8 +3976,9 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg EA) {
Action::OwningExprResult
Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
SourceLocation RParenLoc, ExprArg Op,
- QualType Ty) {
+ TypeSourceInfo *TInfo) {
ParenListExpr *PE = (ParenListExpr *)Op.get();
+ QualType Ty = TInfo->getType();
// If this is an altivec initializer, '(' type ')' '(' init, ..., init ')'
// then handle it as such.
@@ -3982,13 +3998,12 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
InitListExpr *E = new (Context) InitListExpr(LParenLoc, &initExprs[0],
initExprs.size(), RParenLoc);
E->setType(Ty);
- return ActOnCompoundLiteral(LParenLoc, Ty.getAsOpaquePtr(), RParenLoc,
- Owned(E));
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, Owned(E));
} else {
// This is not an AltiVec-style cast, so turn the ParenListExpr into a
// sequence of BinOp comma operators.
Op = MaybeConvertParenListExprToParenExpr(S, move(Op));
- return ActOnCastExpr(S, LParenLoc, Ty.getAsOpaquePtr(), RParenLoc,move(Op));
+ return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, move(Op));
}
}
@@ -4702,8 +4717,9 @@ static void ConstructTransparentUnion(ASTContext &C, Expr *&E,
// Build a compound literal constructing a value of the transparent
// union type from this initializer list.
- E = new (C) CompoundLiteralExpr(SourceLocation(), UnionType, Initializer,
- false);
+ TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
+ E = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
+ Initializer, false);
}
Sema::AssignConvertType
@@ -6785,10 +6801,13 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
- E = CurBlock->TheDecl->param_end(); AI != E; ++AI)
+ E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
+ (*AI)->setOwningFunction(CurBlock->TheDecl);
+
// If this has an identifier, add it to the scope stack.
if ((*AI)->getIdentifier())
PushOnScopeChains(*AI, CurBlock->TheScope);
+ }
// Check for a valid sentinel attribute on this block.
if (!CurBlock->isVariadic &&
@@ -6868,6 +6887,26 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
CurFunctionNeedsScopeChecking = BSI->SavedFunctionNeedsScopeChecking;
BSI->TheDecl->setBody(body.takeAs<CompoundStmt>());
+
+ bool Good = true;
+ // Check goto/label use.
+ for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
+ I = BSI->LabelMap.begin(), E = BSI->LabelMap.end(); I != E; ++I) {
+ LabelStmt *L = I->second;
+
+ // Verify that we have no forward references left. If so, there was a goto
+ // or address of a label taken, but no definition of it.
+ if (L->getSubStmt() != 0)
+ continue;
+
+ // Emit error.
+ Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
+ Good = false;
+ }
+ BSI->LabelMap.clear();
+ if (!Good)
+ return ExprError();
+
AnalysisContext AC(BSI->TheDecl);
CheckFallThroughForBlock(BlockTy, BSI->TheDecl->getBody(), AC);
CheckUnreachable(AC);
@@ -7203,8 +7242,15 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
AlreadyInstantiated = true;
}
- if (!AlreadyInstantiated)
- PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
+ if (!AlreadyInstantiated) {
+ if (isa<CXXRecordDecl>(Function->getDeclContext()) &&
+ cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
+ PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
+ Loc));
+ else
+ PendingImplicitInstantiations.push_back(std::make_pair(Function,
+ Loc));
+ }
}
// FIXME: keep track of references to static functions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d10e11fdb4a3..b004fc3dba72 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -196,8 +196,10 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
assert(TypeRep && "Missing type!");
- // FIXME: Preserve type source info.
- QualType Ty = GetTypeFromParser(TypeRep);
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(TypeRep, &TInfo);
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
unsigned NumExprs = exprs.size();
Expr **Exprs = (Expr**)exprs.get();
SourceLocation TyBeginLoc = TypeRange.getBegin();
@@ -252,7 +254,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
}
return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
- Ty, TyBeginLoc, Kind,
+ TInfo, TyBeginLoc, Kind,
Exprs[0], RParenLoc));
}
@@ -891,9 +893,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (const RecordType *Record = Type->getAs<RecordType>()) {
llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
- const UnresolvedSet *Conversions = RD->getVisibleConversionFunctions();
+ const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
// Skip over templated conversion functions; they aren't considered.
if (isa<FunctionTemplateDecl>(*I))
@@ -1448,12 +1450,14 @@ QualType Sema::CheckPointerToMemberOperands(
// overkill?
if (!IsDerivedFrom(LType, Class, Paths) ||
Paths.isAmbiguous(Context.getCanonicalType(Class))) {
- const char *ReplaceStr = isIndirect ? ".*" : "->*";
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
- << (int)isIndirect << lex->getType() <<
- CodeModificationHint::CreateReplacement(SourceRange(Loc), ReplaceStr);
+ << (int)isIndirect << lex->getType();
return QualType();
}
+ // Cast LHS to type of use.
+ QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
+ bool isLValue = !isIndirect && lex->isLvalue(Context) == Expr::LV_Valid;
+ ImpCastExprToType(lex, UseType, CastExpr::CK_DerivedToBase, isLValue);
}
if (isa<CXXZeroInitValueExpr>(rex->IgnoreParens())) {
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 85889fa5d6d9..ea8f4e3e890f 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -398,7 +398,17 @@ Sema::ExprResult Sema::ActOnClassMessage(
return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
selectorLoc, rbrac, Args, NumArgs);
}
- return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
+ else if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(SuperDecl)) {
+ const ObjCInterfaceType *OCIT;
+ OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
+ if (!OCIT) {
+ Diag(receiverLoc, diag::err_invalid_receiver_to_message);
+ return true;
+ }
+ ClassDecl = OCIT->getDecl();
+ }
+ else
+ return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
}
} else
ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 1970f56e284b..fd62e1afce4f 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -382,7 +382,8 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
if (hadError)
return;
- if (ElementEntity.getKind() == InitializedEntity::EK_ArrayOrVectorElement)
+ if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement ||
+ ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
ElementEntity.setElementIndex(Init);
if (Init >= NumInits || !ILE->getInit(Init)) {
@@ -1828,12 +1829,15 @@ bool Sema::CheckInitList(const InitializedEntity &Entity,
InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
const InitializedEntity &Parent)
- : Kind(EK_ArrayOrVectorElement), Parent(&Parent), Index(Index)
+ : Parent(&Parent), Index(Index)
{
- if (const ArrayType *AT = Context.getAsArrayType(Parent.getType()))
+ if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
+ Kind = EK_ArrayElement;
Type = AT->getElementType();
- else
+ } else {
+ Kind = EK_VectorElement;
Type = Parent.getType()->getAs<VectorType>()->getElementType();
+ }
}
InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
@@ -1862,7 +1866,8 @@ DeclarationName InitializedEntity::getName() const {
case EK_New:
case EK_Temporary:
case EK_Base:
- case EK_ArrayOrVectorElement:
+ case EK_ArrayElement:
+ case EK_VectorElement:
return DeclarationName();
}
@@ -1882,7 +1887,8 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
case EK_New:
case EK_Temporary:
case EK_Base:
- case EK_ArrayOrVectorElement:
+ case EK_ArrayElement:
+ case EK_VectorElement:
return 0;
}
@@ -2141,11 +2147,10 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// refers to.
QualType ToType = AllowRValues? cv1T1 : DestType;
- const UnresolvedSet *Conversions
+ const UnresolvedSetImpl *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
- E = Conversions->end();
- I != E; ++I) {
+ for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -2662,9 +2667,9 @@ static void TryUserDefinedConversion(Sema &S,
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
- const UnresolvedSet *Conversions
+ const UnresolvedSetImpl *Conversions
= SourceRecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
E = Conversions->end();
I != E; ++I) {
NamedDecl *D = *I;
@@ -2917,7 +2922,8 @@ getAssignmentAction(const InitializedEntity &Entity) {
return Sema::AA_Casting;
case InitializedEntity::EK_Member:
- case InitializedEntity::EK_ArrayOrVectorElement:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_VectorElement:
return Sema::AA_Initializing;
}
@@ -2935,7 +2941,8 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity,
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Member:
- case InitializedEntity::EK_ArrayOrVectorElement:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_VectorElement:
return false;
case InitializedEntity::EK_Parameter:
@@ -2981,7 +2988,8 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Member:
- case InitializedEntity::EK_ArrayOrVectorElement:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_VectorElement:
// We don't need to copy for any of these initialized entities.
return move(CurInit);
}
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index 5eb819a69176..d7d3756020f8 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -47,6 +47,11 @@ public:
/// \brief The entity being initialized is an exception object that
/// is being thrown.
EK_Exception,
+ /// \brief The entity being initialized is a non-static data member
+ /// subobject.
+ EK_Member,
+ /// \brief The entity being initialized is an element of an array.
+ EK_ArrayElement,
/// \brief The entity being initialized is an object (or array of
/// objects) allocated via new.
EK_New,
@@ -54,12 +59,10 @@ public:
EK_Temporary,
/// \brief The entity being initialized is a base member subobject.
EK_Base,
- /// \brief The entity being initialized is a non-static data member
- /// subobject.
- EK_Member,
- /// \brief The entity being initialized is an element of an array
+ /// \brief The entity being initialized is an element of a vector.
/// or vector.
- EK_ArrayOrVectorElement
+ EK_VectorElement
+
};
private:
@@ -211,7 +214,7 @@ public:
/// \brief If this is already the initializer for an array or vector
/// element, sets the element index.
void setElementIndex(unsigned Index) {
- assert(getKind() == EK_ArrayOrVectorElement);
+ assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement);
this->Index = Index;
}
};
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index cda245deba13..f5d2a7d89988 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -317,16 +317,16 @@ void LookupResult::resolveKind() {
// Fast case: no possible ambiguity.
if (N == 0) {
- assert(ResultKind == NotFound);
+ assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation);
return;
}
// If there's a single decl, we need to examine it to decide what
// kind of lookup this is.
if (N == 1) {
- if (isa<FunctionTemplateDecl>(Decls[0]))
+ if (isa<FunctionTemplateDecl>(*Decls.begin()))
ResultKind = FoundOverloaded;
- else if (isa<UnresolvedUsingValueDecl>(Decls[0]))
+ else if (isa<UnresolvedUsingValueDecl>(*Decls.begin()))
ResultKind = FoundUnresolvedValue;
return;
}
@@ -445,8 +445,9 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
- if (R.isAcceptableDecl(*I)) {
- R.addDecl(*I);
+ NamedDecl *D = *I;
+ if (R.isAcceptableDecl(D)) {
+ R.addDecl(D);
Found = true;
}
}
@@ -463,10 +464,9 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
if (!Record->isDefinition())
return Found;
- const UnresolvedSet *Unresolved = Record->getConversionFunctions();
- for (UnresolvedSet::iterator U = Unresolved->begin(),
- UEnd = Unresolved->end();
- U != UEnd; ++U) {
+ const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
+ for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
+ UEnd = Unresolved->end(); U != UEnd; ++U) {
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
if (!ConvTemplate)
continue;
@@ -967,6 +967,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// Perform qualified name lookup into the LookupCtx.
if (LookupDirect(R, LookupCtx)) {
R.resolveKind();
+ if (isa<CXXRecordDecl>(LookupCtx))
+ R.setNamingClass(cast<CXXRecordDecl>(LookupCtx));
return true;
}
@@ -1039,6 +1041,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
R.getLookupName().getAsOpaquePtr(), Paths))
return false;
+ R.setNamingClass(LookupRec);
+
// C++ [class.member.lookup]p2:
// [...] If the resulting set of declarations are not all from
// sub-objects of the same type, or the set has a nonstatic member
@@ -1048,10 +1052,15 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// FIXME: support using declarations!
QualType SubobjectType;
int SubobjectNumber = 0;
+ AccessSpecifier SubobjectAccess = AS_private;
for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
Path != PathEnd; ++Path) {
const CXXBasePathElement &PathElement = Path->back();
+ // Pick the best (i.e. most permissive i.e. numerically lowest) access
+ // across all paths.
+ SubobjectAccess = std::min(SubobjectAccess, Path->Access);
+
// Determine whether we're looking at a distinct sub-object or not.
if (SubobjectType.isNull()) {
// This is the first subobject we've looked at. Record its type.
@@ -1106,8 +1115,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// Lookup in a base class succeeded; return these results.
DeclContext::lookup_iterator I, E;
- for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I)
- R.addDecl(*I);
+ for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) {
+ NamedDecl *D = *I;
+ AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
+ D->getAccess());
+ R.addDecl(D, AS);
+ }
R.resolveKind();
return true;
}
@@ -1243,7 +1256,12 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
Diag((*DI)->getLocation(), diag::note_hiding_object);
// For recovery purposes, go ahead and implement the hiding.
- Result.hideDecls(TagDecls);
+ LookupResult::Filter F = Result.makeFilter();
+ while (F.hasNext()) {
+ if (TagDecls.count(F.next()))
+ F.erase();
+ }
+ F.done();
return true;
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 6ec4d1b60018..44a8f15e57b6 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -25,7 +25,6 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
-#include <cstdio>
namespace clang {
@@ -183,51 +182,53 @@ isPointerConversionToVoidPointer(ASTContext& Context) const {
/// DebugPrint - Print this standard conversion sequence to standard
/// error. Useful for debugging overloading issues.
void StandardConversionSequence::DebugPrint() const {
+ llvm::raw_ostream &OS = llvm::errs();
bool PrintedSomething = false;
if (First != ICK_Identity) {
- fprintf(stderr, "%s", GetImplicitConversionName(First));
+ OS << GetImplicitConversionName(First);
PrintedSomething = true;
}
if (Second != ICK_Identity) {
if (PrintedSomething) {
- fprintf(stderr, " -> ");
+ OS << " -> ";
}
- fprintf(stderr, "%s", GetImplicitConversionName(Second));
+ OS << GetImplicitConversionName(Second);
if (CopyConstructor) {
- fprintf(stderr, " (by copy constructor)");
+ OS << " (by copy constructor)";
} else if (DirectBinding) {
- fprintf(stderr, " (direct reference binding)");
+ OS << " (direct reference binding)";
} else if (ReferenceBinding) {
- fprintf(stderr, " (reference binding)");
+ OS << " (reference binding)";
}
PrintedSomething = true;
}
if (Third != ICK_Identity) {
if (PrintedSomething) {
- fprintf(stderr, " -> ");
+ OS << " -> ";
}
- fprintf(stderr, "%s", GetImplicitConversionName(Third));
+ OS << GetImplicitConversionName(Third);
PrintedSomething = true;
}
if (!PrintedSomething) {
- fprintf(stderr, "No conversions required");
+ OS << "No conversions required";
}
}
/// DebugPrint - Print this user-defined conversion sequence to standard
/// error. Useful for debugging overloading issues.
void UserDefinedConversionSequence::DebugPrint() const {
+ llvm::raw_ostream &OS = llvm::errs();
if (Before.First || Before.Second || Before.Third) {
Before.DebugPrint();
- fprintf(stderr, " -> ");
+ OS << " -> ";
}
- fprintf(stderr, "'%s'", ConversionFunction->getNameAsString().c_str());
+ OS << "'" << ConversionFunction->getNameAsString() << "'";
if (After.First || After.Second || After.Third) {
- fprintf(stderr, " -> ");
+ OS << " -> ";
After.DebugPrint();
}
}
@@ -235,27 +236,28 @@ void UserDefinedConversionSequence::DebugPrint() const {
/// DebugPrint - Print this implicit conversion sequence to standard
/// error. Useful for debugging overloading issues.
void ImplicitConversionSequence::DebugPrint() const {
+ llvm::raw_ostream &OS = llvm::errs();
switch (ConversionKind) {
case StandardConversion:
- fprintf(stderr, "Standard conversion: ");
+ OS << "Standard conversion: ";
Standard.DebugPrint();
break;
case UserDefinedConversion:
- fprintf(stderr, "User-defined conversion: ");
+ OS << "User-defined conversion: ";
UserDefined.DebugPrint();
break;
case EllipsisConversion:
- fprintf(stderr, "Ellipsis conversion");
+ OS << "Ellipsis conversion";
break;
case AmbiguousConversion:
- fprintf(stderr, "Ambiguous conversion");
+ OS << "Ambiguous conversion";
break;
case BadConversion:
- fprintf(stderr, "Bad conversion");
+ OS << "Bad conversion";
break;
}
- fprintf(stderr, "\n");
+ OS << "\n";
}
void AmbiguousConversionSequence::construct() {
@@ -1100,7 +1102,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
bool &IncompatibleObjC) {
if (!getLangOptions().ObjC1)
return false;
-
+
// First, we handle all conversions on ObjC object pointer types.
const ObjCObjectPointerType* ToObjCPtr = ToType->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *FromObjCPtr =
@@ -1141,8 +1143,23 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
QualType ToPointeeType;
if (const PointerType *ToCPtr = ToType->getAs<PointerType>())
ToPointeeType = ToCPtr->getPointeeType();
- else if (const BlockPointerType *ToBlockPtr = ToType->getAs<BlockPointerType>())
+ else if (const BlockPointerType *ToBlockPtr =
+ ToType->getAs<BlockPointerType>()) {
+ // Objective C++: We're able to convert from a pointer to any object
+ // to a block pointer type.
+ if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) {
+ ConvertedType = ToType;
+ return true;
+ }
ToPointeeType = ToBlockPtr->getPointeeType();
+ }
+ else if (FromType->getAs<BlockPointerType>() &&
+ ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
+ // Objective C++: We're able to convert from a block pointer type to a
+ // pointer to any object.
+ ConvertedType = ToType;
+ return true;
+ }
else
return false;
@@ -1164,6 +1181,16 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
ConvertedType = ToType;
return true;
}
+ // Allow conversion of pointee being objective-c pointer to another one;
+ // as in I* to id.
+ if (FromPointeeType->getAs<ObjCObjectPointerType>() &&
+ ToPointeeType->getAs<ObjCObjectPointerType>() &&
+ isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
+ IncompatibleObjC)) {
+ ConvertedType = ToType;
+ return true;
+ }
+
// If we have pointers to functions or blocks, check whether the only
// differences in the argument and result types are in Objective-C
// pointer conversions. If so, we permit the conversion (but
@@ -1523,9 +1550,9 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
// Add all of the conversion functions as candidates.
- const UnresolvedSet *Conversions
+ const UnresolvedSetImpl *Conversions
= FromRecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
@@ -2756,7 +2783,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
Candidate.Viable = false;
- Candidate.FailureKind = ovl_fail_bad_conversion;
+ Candidate.FailureKind = ovl_fail_trivial_conversion;
return;
}
@@ -2794,7 +2821,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
case ImplicitConversionSequence::BadConversion:
Candidate.Viable = false;
- Candidate.FailureKind = ovl_fail_bad_conversion;
+ Candidate.FailureKind = ovl_fail_bad_final_conversion;
break;
default:
@@ -2869,6 +2896,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
if (ObjectInit.isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
+ Candidate.Conversions[0] = ObjectInit;
return;
}
@@ -3270,9 +3298,9 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
}
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
- const UnresolvedSet *Conversions
+ const UnresolvedSetImpl *Conversions
= ClassDecl->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
// Skip conversion function templates; they don't tell us anything
@@ -3334,10 +3362,10 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
}
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
- const UnresolvedSet *Conversions =
+ const UnresolvedSetImpl *Conversions =
ClassDecl->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*I)) {
QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
@@ -4386,7 +4414,8 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
QualType FromTy = Conv.Bad.getFromType();
QualType ToTy = Conv.Bad.getToType();
- // Do some hand-waving analysis to see if the non-viability is due to a
+ // Do some hand-waving analysis to see if the non-viability is due
+ // to a qualifier mismatch.
CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
CanQualType CToTy = S.Context.getCanonicalType(ToTy);
if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>())
@@ -4436,6 +4465,20 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
return;
}
+ // Diagnose references or pointers to incomplete types differently,
+ // since it's far from impossible that the incompleteness triggered
+ // the failure.
+ QualType TempFromTy = FromTy.getNonReferenceType();
+ if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
+ TempFromTy = PTy->getPointeeType();
+ if (TempFromTy->isIncompleteType()) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ return;
+ }
+
// TODO: specialize more based on the kind of mismatch
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
<< (unsigned) FnKind << FnDesc
@@ -4503,6 +4546,8 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
return DiagnoseArityMismatch(S, Cand, NumArgs);
case ovl_fail_bad_deduction:
+ case ovl_fail_trivial_conversion:
+ case ovl_fail_bad_final_conversion:
return S.NoteOverloadCandidate(Fn);
case ovl_fail_bad_conversion:
@@ -4582,12 +4627,23 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
}
}
+SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
+ if (Cand->Function)
+ return Cand->Function->getLocation();
+ if (Cand->IsSurrogate)
+ return Cand->Surrogate->getLocation();
+ return SourceLocation();
+}
+
struct CompareOverloadCandidatesForDisplay {
Sema &S;
CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {}
bool operator()(const OverloadCandidate *L,
const OverloadCandidate *R) {
+ // Fast-path this check.
+ if (L == R) return false;
+
// Order first by viability.
if (L->Viable) {
if (!R->Viable) return true;
@@ -4600,25 +4656,132 @@ struct CompareOverloadCandidatesForDisplay {
} else if (R->Viable)
return false;
- // Put declared functions first.
- if (L->Function) {
- if (!R->Function) return true;
- return S.SourceMgr.isBeforeInTranslationUnit(L->Function->getLocation(),
- R->Function->getLocation());
- } else if (R->Function) return false;
-
- // Then surrogates.
- if (L->IsSurrogate) {
- if (!R->IsSurrogate) return true;
- return S.SourceMgr.isBeforeInTranslationUnit(L->Surrogate->getLocation(),
- R->Surrogate->getLocation());
- } else if (R->IsSurrogate) return false;
-
- // And builtins just come in a jumble.
- return false;
+ assert(L->Viable == R->Viable);
+
+ // Criteria by which we can sort non-viable candidates:
+ if (!L->Viable) {
+ // 1. Arity mismatches come after other candidates.
+ if (L->FailureKind == ovl_fail_too_many_arguments ||
+ L->FailureKind == ovl_fail_too_few_arguments)
+ return false;
+ if (R->FailureKind == ovl_fail_too_many_arguments ||
+ R->FailureKind == ovl_fail_too_few_arguments)
+ return true;
+
+ // 2. Bad conversions come first and are ordered by the number
+ // of bad conversions and quality of good conversions.
+ if (L->FailureKind == ovl_fail_bad_conversion) {
+ if (R->FailureKind != ovl_fail_bad_conversion)
+ return true;
+
+ // If there's any ordering between the defined conversions...
+ // FIXME: this might not be transitive.
+ assert(L->Conversions.size() == R->Conversions.size());
+
+ int leftBetter = 0;
+ for (unsigned I = 0, E = L->Conversions.size(); I != E; ++I) {
+ switch (S.CompareImplicitConversionSequences(L->Conversions[I],
+ R->Conversions[I])) {
+ case ImplicitConversionSequence::Better:
+ leftBetter++;
+ break;
+
+ case ImplicitConversionSequence::Worse:
+ leftBetter--;
+ break;
+
+ case ImplicitConversionSequence::Indistinguishable:
+ break;
+ }
+ }
+ if (leftBetter > 0) return true;
+ if (leftBetter < 0) return false;
+
+ } else if (R->FailureKind == ovl_fail_bad_conversion)
+ return false;
+
+ // TODO: others?
+ }
+
+ // Sort everything else by location.
+ SourceLocation LLoc = GetLocationForCandidate(L);
+ SourceLocation RLoc = GetLocationForCandidate(R);
+
+ // Put candidates without locations (e.g. builtins) at the end.
+ if (LLoc.isInvalid()) return false;
+ if (RLoc.isInvalid()) return true;
+
+ return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
}
};
+/// CompleteNonViableCandidate - Normally, overload resolution only
+/// computes up to the first
+void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
+ Expr **Args, unsigned NumArgs) {
+ assert(!Cand->Viable);
+
+ // Don't do anything on failures other than bad conversion.
+ if (Cand->FailureKind != ovl_fail_bad_conversion) return;
+
+ // Skip forward to the first bad conversion.
+ unsigned ConvIdx = 0;
+ unsigned ConvCount = Cand->Conversions.size();
+ while (true) {
+ assert(ConvIdx != ConvCount && "no bad conversion in candidate");
+ ConvIdx++;
+ if (Cand->Conversions[ConvIdx - 1].isBad())
+ break;
+ }
+
+ if (ConvIdx == ConvCount)
+ return;
+
+ // FIXME: these should probably be preserved from the overload
+ // operation somehow.
+ bool SuppressUserConversions = false;
+ bool ForceRValue = false;
+
+ const FunctionProtoType* Proto;
+ unsigned ArgIdx = ConvIdx;
+
+ if (Cand->IsSurrogate) {
+ QualType ConvType
+ = Cand->Surrogate->getConversionType().getNonReferenceType();
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ ConvType = ConvPtrType->getPointeeType();
+ Proto = ConvType->getAs<FunctionProtoType>();
+ ArgIdx--;
+ } else if (Cand->Function) {
+ Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
+ if (isa<CXXMethodDecl>(Cand->Function) &&
+ !isa<CXXConstructorDecl>(Cand->Function))
+ ArgIdx--;
+ } else {
+ // Builtin binary operator with a bad first conversion.
+ assert(ConvCount <= 3);
+ for (; ConvIdx != ConvCount; ++ConvIdx)
+ Cand->Conversions[ConvIdx]
+ = S.TryCopyInitialization(Args[ConvIdx],
+ Cand->BuiltinTypes.ParamTypes[ConvIdx],
+ SuppressUserConversions, ForceRValue,
+ /*InOverloadResolution*/ true);
+ return;
+ }
+
+ // Fill in the rest of the conversions.
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
+ if (ArgIdx < NumArgsInProto)
+ Cand->Conversions[ConvIdx]
+ = S.TryCopyInitialization(Args[ArgIdx], Proto->getArgType(ArgIdx),
+ SuppressUserConversions, ForceRValue,
+ /*InOverloadResolution=*/true);
+ else
+ Cand->Conversions[ConvIdx].setEllipsis();
+ }
+}
+
} // end anonymous namespace
/// PrintOverloadCandidates - When overload resolution fails, prints
@@ -4636,9 +4799,15 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
if (OCD == OCD_AllCandidates) Cands.reserve(CandidateSet.size());
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
LastCand = CandidateSet.end();
- Cand != LastCand; ++Cand)
- if (Cand->Viable || OCD == OCD_AllCandidates)
+ Cand != LastCand; ++Cand) {
+ if (Cand->Viable)
Cands.push_back(Cand);
+ else if (OCD == OCD_AllCandidates) {
+ CompleteNonViableCandidate(*this, Cand, Args, NumArgs);
+ Cands.push_back(Cand);
+ }
+ }
+
std::sort(Cands.begin(), Cands.end(),
CompareOverloadCandidatesForDisplay(*this));
@@ -5909,9 +6078,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// functions for each conversion function declared in an
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
- const UnresolvedSet *Conversions
+ const UnresolvedSetImpl *Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
index 20add007f7c0..f8353e3db1bd 100644
--- a/lib/Sema/SemaOverload.h
+++ b/lib/Sema/SemaOverload.h
@@ -390,7 +390,16 @@ namespace clang {
ovl_fail_too_many_arguments,
ovl_fail_too_few_arguments,
ovl_fail_bad_conversion,
- ovl_fail_bad_deduction
+ ovl_fail_bad_deduction,
+
+ /// This conversion candidate was not considered because it
+ /// duplicates the work of a trivial or derived-to-base
+ /// conversion.
+ ovl_fail_trivial_conversion,
+
+ /// This conversion candidate is not viable because its result
+ /// type is not implicitly convertible to the desired type.
+ ovl_fail_bad_final_conversion
};
/// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 7855a7f60935..0c207fa6e87d 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -412,10 +412,10 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,
llvm::SmallVector<CXXConversionDecl *, 4> ViableConversions;
llvm::SmallVector<CXXConversionDecl *, 4> ExplicitConversions;
if (const RecordType *RecordTy = CondType->getAs<RecordType>()) {
- const UnresolvedSet *Conversions
+ const UnresolvedSetImpl *Conversions
= cast<CXXRecordDecl>(RecordTy->getDecl())
->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(*I))
if (Conversion->getConversionType().getNonReferenceType()
@@ -879,10 +879,6 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Action::OwningStmtResult
Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
IdentifierInfo *LabelII) {
- // If we are in a block, reject all gotos for now.
- if (CurBlock)
- return StmtError(Diag(GotoLoc, diag::err_goto_in_block));
-
// Look up the record for this label identifier.
LabelStmt *&LabelDecl = getLabelMap()[LabelII];
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 2fad8325d4dd..00401560c6a0 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -449,8 +449,8 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
Loc = KeyLoc;
TemplateTypeParmDecl *Param
- = TemplateTypeParmDecl::Create(Context, CurContext, Loc,
- Depth, Position, ParamName, Typename,
+ = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+ Loc, Depth, Position, ParamName, Typename,
Ellipsis);
if (Invalid)
Param->setInvalidDecl();
@@ -572,7 +572,8 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
}
NonTypeTemplateParmDecl *Param
- = NonTypeTemplateParmDecl::Create(Context, CurContext, D.getIdentifierLoc(),
+ = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+ D.getIdentifierLoc(),
Depth, Position, ParamName, T, TInfo);
if (Invalid)
Param->setInvalidDecl();
@@ -625,8 +626,8 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
// Construct the parameter object.
TemplateTemplateParmDecl *Param =
- TemplateTemplateParmDecl::Create(Context, CurContext, TmpLoc, Depth,
- Position, Name,
+ TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+ TmpLoc, Depth, Position, Name,
(TemplateParameterList*)Params);
// Make sure the parameter is valid.
@@ -1586,9 +1587,12 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringContext) {
- if ((ObjectType &&
- computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) ||
- (SS.isSet() && computeDeclContext(SS, EnteringContext))) {
+ DeclContext *LookupCtx = 0;
+ if (SS.isSet())
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ if (!LookupCtx && ObjectType)
+ LookupCtx = computeDeclContext(QualType::getFromOpaquePtr(ObjectType));
+ if (LookupCtx) {
// C++0x [temp.names]p5:
// If a name prefixed by the keyword template is not the name of
// a template, the program is ill-formed. [Note: the keyword
@@ -1608,8 +1612,9 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
TemplateTy Template;
TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
EnteringContext, Template);
- if (TNK == TNK_Non_template &&
- isCurrentInstantiationWithDependentBases(SS)) {
+ if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
+ isa<CXXRecordDecl>(LookupCtx) &&
+ cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) {
// This is a dependent template.
} else if (TNK == TNK_Non_template) {
Diag(Name.getSourceRange().getBegin(),
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e909c4f0b9b6..23a9430d746f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -150,6 +150,7 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
}
+ Typedef->setAccess(D->getAccess());
Owner->addDecl(Typedef);
return Typedef;
@@ -208,6 +209,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
if (D->isOutOfLine())
Var->setLexicalDeclContext(D->getLexicalDeclContext());
+ Var->setAccess(D->getAccess());
+
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
bool Redeclaration = false;
@@ -375,6 +378,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
}
Field->setImplicit(D->isImplicit());
+ Field->setAccess(D->getAccess());
Owner->addDecl(Field);
return Field;
@@ -559,6 +563,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
return Inst;
}
+ Inst->setAccess(D->getAccess());
Owner->addDecl(Inst);
// First, we sort the partial specializations by location, so
@@ -634,6 +639,8 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (!Instantiated)
return 0;
+ Instantiated->setAccess(D->getAccess());
+
// Link the instantiated function template declaration to the function
// template from which it was instantiated.
FunctionTemplateDecl *InstTemplate
@@ -717,7 +724,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
return Info->Function;
}
- Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
+ bool MergeWithParentScope = (TemplateParams != 0) ||
+ !(isa<Decl>(Owner) &&
+ cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+ Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
llvm::SmallVector<ParmVarDecl *, 4> Params;
QualType T = SubstFunctionType(D, Params);
@@ -844,7 +854,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
return Info->Function;
}
- Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
+ bool MergeWithParentScope = (TemplateParams != 0) ||
+ !(isa<Decl>(Owner) &&
+ cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+ Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
llvm::SmallVector<ParmVarDecl *, 4> Params;
QualType T = SubstFunctionType(D, Params);
@@ -958,6 +971,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
if (D->isPure())
SemaRef.CheckPureMethod(Method, SourceRange());
+ Method->setAccess(D->getAccess());
+
if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
!Method->getFriendObjectKind())
Owner->addDecl(Method);
@@ -997,7 +1012,9 @@ ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
// Allocate the parameter
ParmVarDecl *Param
- = ParmVarDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ = ParmVarDecl::Create(SemaRef.Context,
+ SemaRef.Context.getTranslationUnitDecl(),
+ D->getLocation(),
D->getIdentifier(), T, DI, D->getStorageClass(), 0);
// Mark the default argument as being uninstantiated.
@@ -1542,7 +1559,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Proto->hasAnyExceptionSpec(),
Exceptions.size(),
Exceptions.data(),
- Proto->getNoReturnAttr()));
+ Proto->getNoReturnAttr(),
+ Proto->getCallConv()));
}
return false;
@@ -1647,8 +1665,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
// Introduce a new scope where local variable instantiations will be
- // recorded.
- LocalInstantiationScope Scope(*this);
+ // recorded, unless we're actually a member function within a local
+ // class, in which case we need to merge our results with the parent
+ // scope (of the enclosing function).
+ bool MergeWithParentScope = false;
+ if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
+ MergeWithParentScope = Rec->isLocalClass();
+
+ LocalInstantiationScope Scope(*this, MergeWithParentScope);
// Introduce the instantiated function parameters into the local
// instantiation scope.
@@ -1685,6 +1709,11 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
DeclGroupRef DG(Function);
Consumer.HandleTopLevelDecl(DG);
+ // This class may have local implicit instantiations that need to be
+ // instantiation within this scope.
+ PerformPendingImplicitInstantiations(/*LocalOnly=*/true);
+ Scope.Exit();
+
if (Recursive) {
// Instantiate any pending implicit instantiations found during the
// instantiation of this template.
@@ -2217,10 +2246,18 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
/// \brief Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
-void Sema::PerformPendingImplicitInstantiations() {
- while (!PendingImplicitInstantiations.empty()) {
- PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
- PendingImplicitInstantiations.pop_front();
+void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
+ while (!PendingLocalImplicitInstantiations.empty() ||
+ (!LocalOnly && !PendingImplicitInstantiations.empty())) {
+ PendingImplicitInstantiation Inst;
+
+ if (PendingLocalImplicitInstantiations.empty()) {
+ Inst = PendingImplicitInstantiations.front();
+ PendingImplicitInstantiations.pop_front();
+ } else {
+ Inst = PendingLocalImplicitInstantiations.front();
+ PendingLocalImplicitInstantiations.pop_front();
+ }
// Instantiate function definitions
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9515834bb84a..906576115a56 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1374,6 +1374,21 @@ namespace {
Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
+ void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ // By default, use the source location of the type specifier.
+ TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
+ if (TL.needsExtraLocalData()) {
+ // Set info for the written builtin specifiers.
+ TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
+ // Try to have a meaningful source location.
+ if (TL.getWrittenSignSpec() != TSS_unspecified)
+ // Sign spec loc overrides the others (e.g., 'unsigned long').
+ TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
+ else if (TL.getWrittenWidthSpec() != TSW_unspecified)
+ // Width spec loc overrides type spec loc (e.g., 'short int').
+ TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
+ }
+ }
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
TL.initialize(DS.getTypeSpecTypeLoc());
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 445ef0dac797..b2102afdfc42 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1014,15 +1014,12 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCStyleCaseExpr(SourceLocation LParenLoc,
- QualType ExplicitTy,
+ OwningExprResult RebuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
SourceLocation RParenLoc,
ExprArg SubExpr) {
- return getSema().ActOnCastExpr(/*Scope=*/0,
- LParenLoc,
- ExplicitTy.getAsOpaquePtr(),
- RParenLoc,
- move(SubExpr));
+ return getSema().BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc,
+ move(SubExpr));
}
/// \brief Build a new compound literal expression.
@@ -1030,11 +1027,11 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
- QualType T,
+ TypeSourceInfo *TInfo,
SourceLocation RParenLoc,
ExprArg Init) {
- return getSema().ActOnCompoundLiteral(LParenLoc, T.getAsOpaquePtr(),
- RParenLoc, move(Init));
+ return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc,
+ move(Init));
}
/// \brief Build a new extended vector element access expression.
@@ -1194,30 +1191,30 @@ public:
OwningExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc,
Stmt::StmtClass Class,
SourceLocation LAngleLoc,
- QualType T,
+ TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
ExprArg SubExpr,
SourceLocation RParenLoc) {
switch (Class) {
case Stmt::CXXStaticCastExprClass:
- return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, T,
+ return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
move(SubExpr), RParenLoc);
case Stmt::CXXDynamicCastExprClass:
- return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, T,
+ return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
move(SubExpr), RParenLoc);
case Stmt::CXXReinterpretCastExprClass:
- return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, T,
+ return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
move(SubExpr),
RParenLoc);
case Stmt::CXXConstCastExprClass:
- return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, T,
+ return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
move(SubExpr), RParenLoc);
@@ -1235,14 +1232,15 @@ public:
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
- QualType T,
+ TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
ExprArg SubExpr,
SourceLocation RParenLoc) {
- return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_static_cast,
- LAngleLoc, T.getAsOpaquePtr(), RAngleLoc,
- LParenLoc, move(SubExpr), RParenLoc);
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_static_cast,
+ TInfo, move(SubExpr),
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
}
/// \brief Build a new C++ dynamic_cast expression.
@@ -1251,14 +1249,15 @@ public:
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
- QualType T,
+ TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
ExprArg SubExpr,
SourceLocation RParenLoc) {
- return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_dynamic_cast,
- LAngleLoc, T.getAsOpaquePtr(), RAngleLoc,
- LParenLoc, move(SubExpr), RParenLoc);
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_dynamic_cast,
+ TInfo, move(SubExpr),
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
}
/// \brief Build a new C++ reinterpret_cast expression.
@@ -1267,14 +1266,15 @@ public:
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
- QualType T,
+ TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
ExprArg SubExpr,
SourceLocation RParenLoc) {
- return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_reinterpret_cast,
- LAngleLoc, T.getAsOpaquePtr(), RAngleLoc,
- LParenLoc, move(SubExpr), RParenLoc);
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_reinterpret_cast,
+ TInfo, move(SubExpr),
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
}
/// \brief Build a new C++ const_cast expression.
@@ -1283,14 +1283,15 @@ public:
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
- QualType T,
+ TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
ExprArg SubExpr,
SourceLocation RParenLoc) {
- return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_const_cast,
- LAngleLoc, T.getAsOpaquePtr(), RAngleLoc,
- LParenLoc, move(SubExpr), RParenLoc);
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_const_cast,
+ TInfo, move(SubExpr),
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
}
/// \brief Build a new C++ functional-style cast expression.
@@ -1298,13 +1299,13 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildCXXFunctionalCastExpr(SourceRange TypeRange,
- QualType T,
+ TypeSourceInfo *TInfo,
SourceLocation LParenLoc,
ExprArg SubExpr,
SourceLocation RParenLoc) {
void *Sub = SubExpr.takeAs<Expr>();
return getSema().ActOnCXXTypeConstructExpr(TypeRange,
- T.getAsOpaquePtr(),
+ TInfo->getType().getAsOpaquePtr(),
LParenLoc,
Sema::MultiExprArg(getSema(), &Sub, 1),
/*CommaLocs=*/0,
@@ -2137,7 +2138,11 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
template<typename Derived>
QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
BuiltinTypeLoc T) {
- return TransformTypeSpecType(TLB, T);
+ BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType());
+ NewT.setBuiltinLoc(T.getBuiltinLoc());
+ if (T.needsExtraLocalData())
+ NewT.getWrittenBuiltinSpecs() = T.getWrittenBuiltinSpecs();
+ return T.getType();
}
template<typename Derived>
@@ -3815,15 +3820,17 @@ TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
- QualType T;
+ TypeSourceInfo *OldT;
+ TypeSourceInfo *NewT;
{
// FIXME: Source location isn't quite accurate.
SourceLocation TypeStartLoc
= SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
TemporaryBase Rebase(*this, TypeStartLoc, DeclarationName());
- T = getDerived().TransformType(E->getTypeAsWritten());
- if (T.isNull())
+ OldT = E->getTypeInfoAsWritten();
+ NewT = getDerived().TransformType(OldT);
+ if (!NewT)
return SemaRef.ExprError();
}
@@ -3833,11 +3840,12 @@ TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
return SemaRef.ExprError();
if (!getDerived().AlwaysRebuild() &&
- T == E->getTypeAsWritten() &&
+ OldT == NewT &&
SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildCStyleCaseExpr(E->getLParenLoc(), T,
+ return getDerived().RebuildCStyleCastExpr(E->getLParenLoc(),
+ NewT,
E->getRParenLoc(),
move(SubExpr));
}
@@ -3845,28 +3853,25 @@ TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
- QualType T;
- {
- // FIXME: Source location isn't quite accurate.
- SourceLocation FakeTypeLoc
- = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
- TemporaryBase Rebase(*this, FakeTypeLoc, DeclarationName());
-
- T = getDerived().TransformType(E->getType());
- if (T.isNull())
- return SemaRef.ExprError();
- }
+ TypeSourceInfo *OldT = E->getTypeSourceInfo();
+ TypeSourceInfo *NewT = getDerived().TransformType(OldT);
+ if (!NewT)
+ return SemaRef.ExprError();
OwningExprResult Init = getDerived().TransformExpr(E->getInitializer());
if (Init.isInvalid())
return SemaRef.ExprError();
if (!getDerived().AlwaysRebuild() &&
- T == E->getType() &&
+ OldT == NewT &&
Init.get() == E->getInitializer())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), T,
+ // Note: the expression type doesn't necessarily match the
+ // type-as-written, but that's okay, because it should always be
+ // derivable from the initializer.
+
+ return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT,
/*FIXME:*/E->getInitializer()->getLocEnd(),
move(Init));
}
@@ -4237,15 +4242,17 @@ TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
- QualType ExplicitTy;
+ TypeSourceInfo *OldT;
+ TypeSourceInfo *NewT;
{
// FIXME: Source location isn't quite accurate.
SourceLocation TypeStartLoc
= SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
TemporaryBase Rebase(*this, TypeStartLoc, DeclarationName());
- ExplicitTy = getDerived().TransformType(E->getTypeAsWritten());
- if (ExplicitTy.isNull())
+ OldT = E->getTypeInfoAsWritten();
+ NewT = getDerived().TransformType(OldT);
+ if (!NewT)
return SemaRef.ExprError();
}
@@ -4255,7 +4262,7 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
return SemaRef.ExprError();
if (!getDerived().AlwaysRebuild() &&
- ExplicitTy == E->getTypeAsWritten() &&
+ OldT == NewT &&
SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E->Retain());
@@ -4269,7 +4276,7 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
E->getStmtClass(),
FakeLAngleLoc,
- ExplicitTy,
+ NewT,
FakeRAngleLoc,
FakeRAngleLoc,
move(SubExpr),
@@ -4305,12 +4312,14 @@ template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
CXXFunctionalCastExpr *E) {
- QualType ExplicitTy;
+ TypeSourceInfo *OldT;
+ TypeSourceInfo *NewT;
{
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
- ExplicitTy = getDerived().TransformType(E->getTypeAsWritten());
- if (ExplicitTy.isNull())
+ OldT = E->getTypeInfoAsWritten();
+ NewT = getDerived().TransformType(OldT);
+ if (!NewT)
return SemaRef.ExprError();
}
@@ -4320,14 +4329,14 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
return SemaRef.ExprError();
if (!getDerived().AlwaysRebuild() &&
- ExplicitTy == E->getTypeAsWritten() &&
+ OldT == NewT &&
SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E->Retain());
// FIXME: The end of the type's source range is wrong
return getDerived().RebuildCXXFunctionalCastExpr(
/*FIXME:*/SourceRange(E->getTypeBeginLoc()),
- ExplicitTy,
+ NewT,
/*FIXME:*/E->getSubExpr()->getLocStart(),
move(SubExpr),
E->getRParenLoc());
diff --git a/test/Analysis/NSString-failed-cases.m b/test/Analysis/NSString-failed-cases.m
deleted file mode 100644
index 2b8242f0d019..000000000000
--- a/test/Analysis/NSString-failed-cases.m
+++ /dev/null
@@ -1,115 +0,0 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
-// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
-// XFAIL: *
-
-//===----------------------------------------------------------------------===//
-// The following code is reduced using delta-debugging from
-// Foundation.h (Mac OS X).
-//
-// It includes the basic definitions for the test cases below.
-// Not directly including Foundation.h directly makes this test case
-// both svelte and portable to non-Mac platforms.
-//===----------------------------------------------------------------------===//
-
-#ifdef TEST_64
-typedef long long int64_t;
-_Bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
-#define COMPARE_SWAP_BARRIER OSAtomicCompareAndSwap64Barrier
-typedef int64_t intptr_t;
-#else
-typedef int int32_t;
-_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
-#define COMPARE_SWAP_BARRIER OSAtomicCompareAndSwap32Barrier
-typedef int32_t intptr_t;
-#endif
-
-typedef const void * CFTypeRef;
-typedef const struct __CFString * CFStringRef;
-typedef const struct __CFAllocator * CFAllocatorRef;
-extern const CFAllocatorRef kCFAllocatorDefault;
-extern CFTypeRef CFRetain(CFTypeRef cf);
-void CFRelease(CFTypeRef cf);
-typedef const struct __CFDictionary * CFDictionaryRef;
-const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key);
-extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...);
-typedef signed char BOOL;
-typedef int NSInteger;
-typedef unsigned int NSUInteger;
-@class NSString, Protocol;
-extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
-typedef NSInteger NSComparisonResult;
-typedef struct _NSZone NSZone;
-@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
-@protocol NSObject
-- (BOOL)isEqual:(id)object;
-- (oneway void)release;
-- (id)retain;
-- (id)autorelease;
-@end
-@protocol NSCopying
-- (id)copyWithZone:(NSZone *)zone;
-@end
-@protocol NSMutableCopying
-- (id)mutableCopyWithZone:(NSZone *)zone;
-@end
-@protocol NSCoding
-- (void)encodeWithCoder:(NSCoder *)aCoder;
-@end
-@interface NSObject <NSObject> {}
-- (id)init;
-+ (id)alloc;
-@end
-extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
-typedef struct {} NSFastEnumerationState;
-@protocol NSFastEnumeration
-- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
-@end
-@class NSString;
-typedef struct _NSRange {} NSRange;
-@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
-- (NSUInteger)count;
-@end
-@interface NSMutableArray : NSArray
-- (void)addObject:(id)anObject;
-- (id)initWithCapacity:(NSUInteger)numItems;
-@end
-typedef unsigned short unichar;
-@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale;
-typedef NSUInteger NSStringCompareOptions;
-@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
-- (NSComparisonResult)compare:(NSString *)string;
-- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;
-- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange;
-- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale;
-- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string;
-- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator;
-+ (id)stringWithFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2)));
-@end
-@interface NSSimpleCString : NSString {} @end
-@interface NSConstantString : NSSimpleCString @end
-extern void *_NSConstantStringClassReference;
-
-//===----------------------------------------------------------------------===//
-// Test cases. These should all be merged into NSString.m once these tests
-// stop reporting leaks.
-//===----------------------------------------------------------------------===//
-
-// FIXME: THIS TEST CASE INCORRECTLY REPORTS A LEAK.
-void testOSCompareAndSwapXXBarrier_parameter(NSString **old) {
- NSString *s = [[NSString alloc] init]; // no-warning
- if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) old))
- [s release];
- else
- [*old release];
-}
-
-// FIXME: THIS TEST CASE INCORRECTLY REPORTS A LEAK.
-void testOSCompareAndSwapXXBarrier_parameter_no_direct_release(NSString **old) {
- NSString *s = [[NSString alloc] init]; // no-warning
- if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) old))
- return;
- else
- [*old release];
-}
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index 4d771eeb4bd3..7d2b71877b91 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -51,3 +51,9 @@ void f6() {
else
free(p);
}
+
+char *doit2();
+void pr6069() {
+ char *buf = doit2();
+ free(buf);
+}
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index 9543a98fe323..ae42dca3b45e 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -811,3 +811,29 @@ int pr6033(int x) {
return x % y; // expected-warning{{The right operand of '%' is a garbage value}}
}
+struct trie {
+ struct trie* next;
+};
+
+struct kwset {
+ struct trie *trie;
+ unsigned char delta[10];
+ struct trie* next[10];
+ int d;
+};
+
+typedef struct trie trie_t;
+typedef struct kwset kwset_t;
+
+void f(kwset_t *kws, char const *p, char const *q) {
+ struct trie const *trie;
+ struct trie * const *next = kws->next;
+ register unsigned char c;
+ register char const *end = p;
+ register char const *lim = q;
+ register int d = 1;
+ register unsigned char const *delta = kws->delta;
+
+ d = delta[c = (end+=d)[-1]]; // no-warning
+ trie = next[c];
+}
diff --git a/test/Analysis/outofbound.c b/test/Analysis/outofbound.c
index 2142e9e1f73b..68e77caa36bd 100644
--- a/test/Analysis/outofbound.c
+++ b/test/Analysis/outofbound.c
@@ -1,7 +1,15 @@
-// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-experimental-checks -checker-cfref -analyzer-store=region -verify %s
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
char f1() {
char* s = "abcd";
char c = s[4]; // no-warning
return s[5] + c; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
}
+
+void f2() {
+ int *p = malloc(12);
+ p[3] = 4; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
+}
diff --git a/test/CXX/class.access/class.access.base/p1.cpp b/test/CXX/class.access/class.access.base/p1.cpp
new file mode 100644
index 000000000000..fd0d9f68e1e2
--- /dev/null
+++ b/test/CXX/class.access/class.access.base/p1.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s
+
+// C++0x [class.access.base]p1(a):
+// If a class is declared to be a base class for another class using
+// the public access specifier, the public members of the base class
+// are accessible as public members of the derived class and protected
+// members of the base class are accessible as protected members of
+// the derived class.
+namespace test0 {
+ class Base {
+ public: int pub; static int spub;
+ protected: int prot; static int sprot; // expected-note 4 {{declared protected here}}
+ private: int priv; static int spriv; // expected-note 8 {{declared private here}}
+ };
+
+ class Test : public Base {
+ void test() {
+ pub++;
+ spub++;
+ prot++;
+ sprot++;
+ priv++; // expected-error {{private member}}
+ spriv++; // expected-error {{private member}}
+
+ Base::pub++;
+ Base::spub++;
+ Base::prot++;
+ Base::sprot++;
+ Base::priv++; // expected-error {{private member}}
+ Base::spriv++; // expected-error {{private member}}
+ }
+ };
+
+ void test(Test *t) {
+ t->pub++;
+ t->spub++;
+ t->prot++; // expected-error {{protected member}}
+ t->sprot++; // expected-error {{protected member}}
+ t->priv++; // expected-error {{private member}}
+ t->spriv++; // expected-error {{private member}}
+
+ t->Base::pub++;
+ t->Base::spub++;
+ t->Base::prot++; // expected-error {{protected member}}
+ t->Base::sprot++; // expected-error {{protected member}}
+ t->Base::priv++; // expected-error {{private member}}
+ t->Base::spriv++; // expected-error {{private member}}
+ }
+}
+
+// C++0x [class.access.base]p1(b):
+// If a class is declared to be a base class for another class using
+// the protected access specifier, the public and protected members
+// of the base class are accessible as protected members of the
+// derived class.
+namespace test1 {
+ class Base { // expected-note 6 {{constrained by protected inheritance}}
+ public: int pub; static int spub; // expected-note 2 {{constrained by protected inheritance}}
+ protected: int prot; static int sprot; // expected-note 4 {{declared protected here}}
+ private: int priv; static int spriv; // expected-note 8 {{declared private here}}
+ };
+
+ class Test : protected Base {
+ void test() {
+ pub++;
+ spub++;
+ prot++;
+ sprot++;
+ priv++; // expected-error {{private member}}
+ spriv++; // expected-error {{private member}}
+
+ Base::pub++;
+ Base::spub++;
+ Base::prot++;
+ Base::sprot++;
+ Base::priv++; // expected-error {{private member}}
+ Base::spriv++; // expected-error {{private member}}
+ }
+ };
+
+ void test(Test *t) {
+ t->pub++; // expected-error {{protected member}}
+ t->spub++; // expected-error {{protected member}}
+ t->prot++; // expected-error {{protected member}}
+ t->sprot++; // expected-error {{protected member}}
+ t->priv++; // expected-error {{private member}}
+ t->spriv++; // expected-error {{private member}}
+
+ // Two possible errors here: one for Base, one for the member
+ t->Base::pub++; // expected-error {{protected member}}
+ t->Base::spub++; // expected-error {{protected member}}
+ t->Base::prot++; // expected-error 2 {{protected member}}
+ t->Base::sprot++; // expected-error 2 {{protected member}}
+ t->Base::priv++; // expected-error {{protected member}} expected-error {{private member}}
+ t->Base::spriv++; // expected-error {{protected member}} expected-error {{private member}}
+ }
+}
+
+// C++0x [class.access.base]p1(b):
+// If a class is declared to be a base class for another class using
+// the private access specifier, the public and protected members of
+// the base class are accessible as private members of the derived
+// class.
+namespace test2 {
+ class Base { //expected-note 6 {{constrained by private inheritance}}
+ public:
+ int pub; // expected-note {{constrained by private inheritance}}
+ static int spub; // expected-note {{constrained by private inheritance}}
+ protected:
+ int prot; // expected-note {{constrained by private inheritance}} \
+ // expected-note {{declared protected here}}
+ static int sprot; // expected-note {{constrained by private inheritance}} \
+ // expected-note {{declared protected here}}
+ private:
+ int priv; // expected-note 4 {{declared private here}}
+ static int spriv; // expected-note 4 {{declared private here}}
+ };
+
+ class Test : private Base { // expected-note 6 {{'private' inheritance specifier here}}
+ void test() {
+ pub++;
+ spub++;
+ prot++;
+ sprot++;
+ priv++; // expected-error {{private member}}
+ spriv++; // expected-error {{private member}}
+
+ Base::pub++;
+ Base::spub++;
+ Base::prot++;
+ Base::sprot++;
+ Base::priv++; // expected-error {{private member}}
+ Base::spriv++; // expected-error {{private member}}
+ }
+ };
+
+ void test(Test *t) {
+ t->pub++; // expected-error {{private member}} expected-error {{inaccessible base class}}
+ t->spub++; // expected-error {{private member}}
+ t->prot++; // expected-error {{private member}} expected-error {{inaccessible base class}}
+ t->sprot++; // expected-error {{private member}}
+ t->priv++; // expected-error {{private member}} expected-error {{inaccessible base class}}
+ t->spriv++; // expected-error {{private member}}
+
+ t->Base::pub++; // expected-error {{private member}} expected-error {{inaccessible base class}}
+ t->Base::spub++; // expected-error {{private member}}
+ t->Base::prot++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{inaccessible base class}}
+ t->Base::sprot++; // expected-error {{protected member}} expected-error {{private member}}
+ t->Base::priv++; // expected-error 2 {{private member}} expected-error {{inaccessible base class}}
+ t->Base::spriv++; // expected-error 2 {{private member}}
+ }
+}
diff --git a/test/CodeCompletion/call.c b/test/CodeCompletion/call.c
new file mode 100644
index 000000000000..8210389ffa56
--- /dev/null
+++ b/test/CodeCompletion/call.c
@@ -0,0 +1,15 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+void f0(float x, float y);
+void f1();
+void test() {
+ f0(0, 0);
+ g0(0, 0);
+ f1(0, 0);
+ // RUN: %clang_cc1 -std=c89 -fsyntax-only -code-completion-at=%s:6:6 %s -o - | FileCheck -check-prefix=CC1 %s
+ // CHECK-CC1: f0(<#float x#>, float y)
+ // RUN: %clang_cc1 -std=c89 -fsyntax-only -code-completion-at=%s:6:9 %s -o - | FileCheck -check-prefix=CC2 %s
+ // CHECK-CC2: f0(float x, <#float y#>)
+ // RUN: %clang_cc1 -std=c89 -fsyntax-only -code-completion-at=%s:8:6 %s -o - | FileCheck -check-prefix=CC3 %s
+ // CHECK-CC3: f1()
+}
diff --git a/test/CodeGen/2009-10-20-GlobalDebug.c b/test/CodeGen/2009-10-20-GlobalDebug.c
index f19ceb1e73c1..99be46996ed5 100644
--- a/test/CodeGen/2009-10-20-GlobalDebug.c
+++ b/test/CodeGen/2009-10-20-GlobalDebug.c
@@ -1,4 +1,4 @@
// RUN: %clang -ccc-host-triple i386-apple-darwin10 -S -g -dA %s -o - | FileCheck %s
int global;
-// CHECK: asciz "global" ## DW_AT_name
+// CHECK: asciz "global" ## External Name
int main() { return 0;}
diff --git a/test/CodeGenCXX/copy-assign-synthesis-3.cpp b/test/CodeGenCXX/copy-assign-synthesis-3.cpp
index 73c2261cddc1..ce4640a7eddb 100644
--- a/test/CodeGenCXX/copy-assign-synthesis-3.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis-3.cpp
@@ -1,18 +1,24 @@
// RUN: %clang_cc1 -emit-llvm-only -verify %s
struct A {
- A& operator=(const A&);
+ A& operator=(A&);
};
struct B {
+ void operator=(B);
+};
+
+struct C {
A a;
- float b;
- int (A::*c)();
- _Complex float d;
- int e[10];
- A f[2];
+ B b;
+ float c;
+ int (A::*d)();
+ _Complex float e;
+ int f[10];
+ A g[2];
+ B h[2];
};
-void a(B& x, B& y) {
+void a(C& x, C& y) {
x = y;
}
diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp
index 705491e3a9b4..cb6e830a49e0 100644
--- a/test/CodeGenCXX/debug-info.cpp
+++ b/test/CodeGenCXX/debug-info.cpp
@@ -18,3 +18,9 @@ void f() {
int B::*a = 0;
void (B::*b)() = 0;
}
+
+namespace EmptyNameCrash {
+ struct A { A(); };
+ typedef struct { A x; } B;
+ B x;
+}
diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp
index 2454ddab774a..e1353a72b396 100644
--- a/test/CodeGenCXX/member-function-pointers.cpp
+++ b/test/CodeGenCXX/member-function-pointers.cpp
@@ -139,3 +139,14 @@ namespace PR5940 {
void (foo::*ptr)(void) = &foo::baz;
}
}
+
+namespace MemberPointerImpCast {
+ struct A {
+ int x;
+ };
+ struct B : public A {
+ };
+ void f(B* obj, void (A::*method)()) {
+ (obj->*method)();
+ }
+}
diff --git a/test/CodeGenCXX/temp-order.cpp b/test/CodeGenCXX/temp-order.cpp
index e1ef7eb260a2..05a9aed2defa 100644
--- a/test/CodeGenCXX/temp-order.cpp
+++ b/test/CodeGenCXX/temp-order.cpp
@@ -167,13 +167,10 @@ void test() {
if (f5() != ORDER4(5, 3, 7, 2))
error();
-// FIXME: Clang/LLVM currently can't fold this to a constant. If the error check
-// is present (since it avoids single-caller inlining). PR5645.
-
-// CHECK: call void @print(i8* {{.*}}, i32 1251552576)
+// CHECK: call void @print(i8* {{.*}}, i32 1251552576)
print("f6", f6());
-// if (f6() != ORDER6(3, 7, 11, 5, 13, 2))
-// error();
+ if (f6() != ORDER6(3, 7, 11, 5, 13, 2))
+ error();
}
diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp
index f7f4c9f15c8f..22e11fd76e31 100644
--- a/test/CodeGenCXX/virt.cpp
+++ b/test/CodeGenCXX/virt.cpp
@@ -17,11 +17,7 @@ struct B {
void B::bar1() { }
void B::bar2() { }
-// CHECK-LP64: __ZTV1B:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI1B
-// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev
-// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev
+// CHECK-LPLL64:@_ZTV1B = constant [4 x i8*] [i8* null, i8* bitcast (%0* @_ZTI1B to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B4bar1Ev to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B4bar2Ev to i8*)]
struct C {
virtual void bee1();
@@ -52,42 +48,8 @@ public:
};
void F::foo() { }
-// CHECK-LP64: __ZTV1F:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI1F
-// CHECK-LP64-NEXT: .quad __ZN1D3booEv
-// CHECK-LP64-NEXT: .quad __ZN1F3fooEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad __ZTI1F
-// CHECK-LP64-NEXT: .quad __ZN2D13barEv
-// CHECK-LP64-NEXT: .quad __ZN2D14bar2Ev
-// CHECK-LP64-NEXT: .quad __ZN2D14bar3Ev
-// CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev
-// CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev
-
-
-int j;
-void *vp;
-void test2() {
- F f;
- static int sz = (char *)(&f.f) - (char *)(&f);
- vp = &sz;
- j = sz;
- // FIXME: These should result in a frontend constant a la fold, no run time
- // initializer
- // CHECK-LPLL64: define void @_Z5test2v()
- // CHECK-LPLL64: = getelementptr inbounds %class.F* %f, i32 0, i32 1
-}
+// CHECK-LPLL64:@_ZTV1F = constant [19 x i8*] [i8* null, i8* inttoptr (i64 16 to i8*), i8* null, i8* null, i8* bitcast (%1* @_ZTI1F to i8*), i8* bitcast (void (%class.test14*)* @_ZN1D3booEv to i8*), i8* bitcast (void (%class.F*)* @_ZN1F3fooEv to i8*), i8* null, i8* null, i8* null, i8* null, i8* null, i8* inttoptr (i64 -16 to i8*), i8* bitcast (%1* @_ZTI1F to i8*), i8* bitcast (void (%struct.D1*)* @_ZN2D13barEv to i8*), i8* bitcast (void (%struct.D1*)* @_ZN2D14bar2Ev to i8*), i8* bitcast (void (%struct.D1*)* @_ZN2D14bar3Ev to i8*), i8* bitcast (void (%struct.D1*)* @_ZN2D14bar4Ev to i8*), i8* bitcast (void (%struct.D1*)* @_ZN2D14bar5Ev to i8*)]
-static_assert(sizeof(F) == sizeof(void*)*4, "invalid vbase size");
struct E {
int e;
@@ -105,6 +67,8 @@ public:
void A::foo1() { }
void A::foo2() { }
+// CHECK-LPLL64:@_ZTV1A = constant [10 x i8*] [i8* null, i8* bitcast (%2* @_ZTI1A to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B4bar1Ev to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B4bar2Ev to i8*), i8* bitcast (void (%class.A*)* @_ZN1A4foo1Ev to i8*), i8* bitcast (void (%class.A*)* @_ZN1A4foo2Ev to i8*), i8* inttoptr (i64 -16 to i8*), i8* bitcast (%2* @_ZTI1A to i8*), i8* bitcast (void (%class.test14*)* @_ZN1C4bee1Ev to i8*), i8* bitcast (void (%class.test14*)* @_ZN1C4bee2Ev to i8*)]
+
int main() {
A a;
B b;
@@ -112,18 +76,6 @@ int main() {
ap->b = 2;
}
-// CHECK-LP64: __ZTV1A:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI1A
-// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev
-// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev
-// CHECK-LP64-NEXT: .quad __ZN1A4foo1Ev
-// CHECK-LP64-NEXT: .quad __ZN1A4foo2Ev
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad __ZTI1A
-// CHECK-LP64-NEXT: .quad __ZN1C4bee1Ev
-// CHECK-LP64-NEXT: .quad __ZN1C4bee2Ev
-
struct test12_A {
virtual void foo0() { }
@@ -136,24 +88,6 @@ struct test12_B : public test12_A {
struct test12_D : public test12_B {
} *test12_pd;
-void test12_foo() {
- test12_pa->foo0();
- test12_pb->foo0();
- test12_pd->foo0();
- test12_pa->foo();
- test12_pb->foo();
- test12_pd->foo();
- test12_pa->test12_A::foo();
-}
-
-// CHECK-LPLL64:define void @_Z10test12_foov() nounwind {
-// CHECK-LPLL64: call void %
-// CHECK-LPLL64: call void %
-// CHECK-LPLL64: call void %
-// CHECK-LPLL64: call void %
-// CHECK-LPLL64: call void %
-// CHECK-LPLL64: call void %
-// CHECK-LPLL64: call void @_ZN8test12_A3fooEv(%class.test14* %{{.*}})
struct test6_B2 { virtual void funcB2(); char b[1000]; };
@@ -162,7 +96,7 @@ struct test6_B1 : virtual test6_B2 { virtual void funcB1(); };
struct test6_D : test6_B2, virtual test6_B1 {
};
-// CHECK-LP64: .zerofill __DATA, __common, _d6, 2024, 4
+// CHECK-LP64: .zerofill __DATA,__common,_d6,2024,4
struct test7_B2 { virtual void funcB2(); };
struct test7_B1 : virtual test7_B2 { virtual void funcB1(); };
@@ -170,7 +104,7 @@ struct test7_B1 : virtual test7_B2 { virtual void funcB1(); };
struct test7_D : test7_B2, virtual test7_B1 {
};
-// CHECK-LP64: .zerofill __DATA, __common, _d7, 16, 3
+// CHECK-LP64: .zerofill __DATA,__common,_d7,16,3
struct test3_B3 { virtual void funcB3(); };
@@ -181,38 +115,13 @@ struct test3_D : virtual test3_B1 {
virtual void funcD() { }
};
-// CHECK-LP64:__ZTV7test3_D:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI7test3_D
-// CHECK-LP64-NEXT: .quad __ZN8test3_B36funcB3Ev
-// CHECK-LP64-NEXT: .quad __ZN8test3_B26funcB2Ev
-// CHECK-LP64-NEXT: .quad __ZN8test3_B16funcB1Ev
-// CHECK-LP64-NEXT: .quad __ZN7test3_D5funcDEv
+// CHECK-LPLL64:@_ZTV7test3_D = weak_odr constant [12 x i8*] [i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* bitcast (%3* @_ZTI7test3_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test3_B36funcB3Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test3_B26funcB2Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test3_B16funcB1Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN7test3_D5funcDEv to i8*)]
+
struct test4_D : virtual B, virtual C {
};
-// CHECK-LP64:__ZTV7test4_D:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI7test4_D
-// CHECK-LP64-NEXT: .quad __ZN1C4bee1Ev
-// CHECK-LP64-NEXT: .quad __ZN1C4bee2Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI7test4_D
-// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev
-// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev
+// CHECK-LPLL64:@_ZTV7test4_D = weak_odr constant [14 x i8*] [i8* null, i8* inttoptr (i64 8 to i8*), i8* null, i8* null, i8* null, i8* bitcast (%1* @_ZTI7test4_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN1C4bee1Ev to i8*), i8* bitcast (void (%class.test14*)* @_ZN1C4bee2Ev to i8*), i8* null, i8* null, i8* inttoptr (i64 -8 to i8*), i8* bitcast (%1* @_ZTI7test4_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B4bar1Ev to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B4bar2Ev to i8*)]
struct test5_B3 { virtual void funcB3(); };
@@ -235,57 +144,7 @@ struct test5_D : virtual test5_B1, virtual test5_B21, virtual test5_B31 {
virtual void funcD() { }
};
-// CHECK-LP64:__ZTV7test5_D:
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .quad 24
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI7test5_D
-// CHECK-LP64-NEXT: .quad __ZN8test5_B36funcB3Ev
-// CHECK-LP64-NEXT: .quad __ZN8test5_B26funcB2Ev
-// CHECK-LP64-NEXT: .quad __ZN8test5_B16funcB1Ev
-// CHECK-LP64-NEXT: .quad __ZN7test5_D5funcDEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI7test5_D
-// CHECK-LP64-NEXT: .quad __ZN9test5_B237funcB23Ev
-// CHECK-LP64-NEXT: .quad __ZN9test5_B227funcB22Ev
-// CHECK-LP64-NEXT: .quad __ZN9test5_B217funcB21Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad __ZTI7test5_D
-// CHECK-LP64-NEXT: .quad __ZN9test5_B337funcB33Ev
-// CHECK-LP64-NEXT: .quad __ZN9test5_B327funcB32Ev
-// CHECK-LP64-NEXT: .quad __ZN9test5_B317funcB31Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad __ZTI7test5_D
-// CHECK-LP64-NEXT: .quad __ZN4B2328funcB232Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551584
-// CHECK-LP64-NEXT: .quad __ZTI7test5_D
-// CHECK-LP64-NEXT: .quad __ZN4B2318funcB231Ev
+// CHECK-LPLL64:@_ZTV7test5_D = weak_odr constant [50 x i8*] [i8* inttoptr (i64 32 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 8 to i8*), i8* inttoptr (i64 8 to i8*), i8* inttoptr (i64 8 to i8*), i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* bitcast (%2* @_ZTI7test5_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test5_B36funcB3Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test5_B26funcB2Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test5_B16funcB1Ev to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN7test5_D5funcDEv to i8*), i8* null, i8* null, i8* null, i8* null, i8* null, i8* inttoptr (i64 -8 to i8*), i8* bitcast (%2* @_ZTI7test5_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test5_B237funcB23Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test5_B227funcB22Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test5_B217funcB21Ev to i8*), i8* null, i8* inttoptr (i64 16 to i8*), i8* null, i8* null, i8* inttoptr (i64 8 to i8*), i8* null, i8* null, i8* inttoptr (i64 -16 to i8*), i8* bitcast (%2* @_ZTI7test5_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test5_B337funcB33Ev to i8*), i8* bitcast (void (%class.test20_D*)* @_ZN9test5_B327funcB32Ev to i8*), i8* bitcast (void (%class.test23_D*)* @_ZN9test5_B317funcB31Ev to i8*), i8* null, i8* inttoptr (i64 -24 to i8*), i8* bitcast (%2* @_ZTI7test5_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN4B2328funcB232Ev to i8*), i8* null, i8* inttoptr (i64 -32 to i8*), i8* bitcast (%2* @_ZTI7test5_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN4B2318funcB231Ev to i8*)]
struct test8_B1 {
virtual void ftest8_B1() { }
@@ -313,75 +172,13 @@ struct test8_B3 {
class test8_D : test8_B1, test8_B2, test8_B3 {
};
-// CHECK-LP64:__ZTV7test8_D:
-// CHECK-LP64-NEXT: .quad 48
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI7test8_D
-// CHECK-LP64-NEXT: .quad __ZN8test8_B19ftest8_B1Ev
-// CHECK-LP64-NEXT: .quad 40
-// CHECK-LP64-NEXT: .quad 24
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI7test8_D
-// CHECK-LP64-NEXT: .quad __ZN9test8_B2a10ftest8_B2aEv
-// CHECK-LP64-NEXT: .quad __ZN8test8_B29ftest8_B2Ev
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad __ZTI7test8_D
-// CHECK-LP64-NEXT: .quad __ZN9test8_B2b10ftest8_B2bEv
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad __ZTI7test8_D
-// CHECK-LP64-NEXT: .quad __ZN8test8_B39ftest8_B3Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551584
-// CHECK-LP64-NEXT: .quad __ZTI7test8_D
-// CHECK-LP64-NEXT: .quad __ZN10test8_B2aa11ftest8_B2aaEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551568
-// CHECK-LP64-NEXT: .quad __ZTI7test8_D
-// CHECK-LP64-NEXT: .quad __ZN10test8_B2ab11ftest8_B2abEv
-
-// CHECK-LP64:__ZTC7test8_D8_8test8_B2:
-// CHECK-LP64-NEXT: .quad 40
-// CHECK-LP64-NEXT: .quad 24
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test8_B2
-// CHECK-LP64-NEXT: .quad __ZN9test8_B2a10ftest8_B2aEv
-// CHECK-LP64-NEXT: .quad __ZN8test8_B29ftest8_B2Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad __ZTI8test8_B2
-// CHECK-LP64-NEXT: .quad __ZN10test8_B2aa11ftest8_B2aaEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551576
-// CHECK-LP64-NEXT: .quad __ZTI8test8_B2
-// CHECK-LP64-NEXT: .quad __ZN10test8_B2ab11ftest8_B2abEv
-
-// CHECK-LP64:__ZTC7test8_D8_9test8_B2a:
-// CHECK-LP64-NEXT: .quad 40
-// CHECK-LP64-NEXT: .quad 24
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI9test8_B2a
-// CHECK-LP64-NEXT: .quad __ZN9test8_B2a10ftest8_B2aEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad __ZTI9test8_B2a
-// CHECK-LP64-NEXT: .quad __ZN10test8_B2aa11ftest8_B2aaEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551576
-// CHECK-LP64-NEXT: .quad __ZTI9test8_B2a
-// CHECK-LP64-NEXT: .quad __ZN10test8_B2ab11ftest8_B2abEv
-
-// CHECK-LP64:__ZTT7test8_D:
-// CHECK-LP64-NEXT: .quad (__ZTV7test8_D) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_8test8_B2) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_9test8_B2a) + 32
-// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_9test8_B2a) + 64
-// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_9test8_B2a) + 96
-// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_8test8_B2) + 72
-// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_8test8_B2) + 104
-// CHECK-LP64-NEXT .quad (__ZTV7test8_D) + 72
-// CHECK-LP64: .quad (__ZTV7test8_D) + 160
-// CHECK-LP64: .quad (__ZTV7test8_D) + 192
+// CHECK-LPLL64:@_ZTV7test8_D = weak_odr constant [25 x i8*] [i8* inttoptr (i64 48 to i8*), i8* inttoptr (i64 32 to i8*), i8* null, i8* bitcast (%2* @_ZTI7test8_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test8_B19ftest8_B1Ev to i8*), i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%2* @_ZTI7test8_D to i8*), i8* bitcast (void (%struct.test10_B2a*)* @_ZN9test8_B2a10ftest8_B2aEv to i8*), i8* bitcast (void (%struct.test15_D*)* @_ZN8test8_B29ftest8_B2Ev to i8*), i8* inttoptr (i64 -16 to i8*), i8* bitcast (%2* @_ZTI7test8_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test8_B2b10ftest8_B2bEv to i8*), i8* inttoptr (i64 -24 to i8*), i8* bitcast (%2* @_ZTI7test8_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test8_B39ftest8_B3Ev to i8*), i8* null, i8* inttoptr (i64 -32 to i8*), i8* bitcast (%2* @_ZTI7test8_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test8_B2aa11ftest8_B2aaEv to i8*), i8* null, i8* inttoptr (i64 -48 to i8*), i8* bitcast (%2* @_ZTI7test8_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test8_B2ab11ftest8_B2abEv to i8*)]
+
+// CHECK-LPLL64:@_ZTC7test8_D8_8test8_B2 = internal constant [14 x i8*] [i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* null, i8* bitcast (%1* @_ZTI8test8_B2 to i8*), i8* bitcast (void (%struct.test10_B2a*)* @_ZN9test8_B2a10ftest8_B2aEv to i8*), i8* bitcast (void (%struct.test15_D*)* @_ZN8test8_B29ftest8_B2Ev to i8*), i8* null, i8* inttoptr (i64 -24 to i8*), i8* bitcast (%1* @_ZTI8test8_B2 to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test8_B2aa11ftest8_B2aaEv to i8*), i8* null, i8* inttoptr (i64 -40 to i8*), i8* bitcast (%1* @_ZTI8test8_B2 to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test8_B2ab11ftest8_B2abEv to i8*)] ; <[14 x i8*]*> [#uses=3]
+
+// CHECK-LPLL64:@_ZTC7test8_D8_9test8_B2a = internal constant [13 x i8*] [i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* null, i8* bitcast (%1* @_ZTI9test8_B2a to i8*), i8* bitcast (void (%struct.test10_B2a*)* @_ZN9test8_B2a10ftest8_B2aEv to i8*), i8* null, i8* inttoptr (i64 -24 to i8*), i8* bitcast (%1* @_ZTI9test8_B2a to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test8_B2aa11ftest8_B2aaEv to i8*), i8* null, i8* inttoptr (i64 -40 to i8*), i8* bitcast (%1* @_ZTI9test8_B2a to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test8_B2ab11ftest8_B2abEv to i8*)] ; <[13 x i8*]*> [#uses=3]
+
+// CHECK-LPLL64:@_ZTT7test8_D = weak_odr constant [10 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTV7test8_D, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTC7test8_D8_8test8_B2, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([13 x i8*]* @_ZTC7test8_D8_9test8_B2a, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([13 x i8*]* @_ZTC7test8_D8_9test8_B2a, i64 0, i64 8) to i8*), i8* bitcast (i8** getelementptr inbounds ([13 x i8*]* @_ZTC7test8_D8_9test8_B2a, i64 0, i64 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTC7test8_D8_8test8_B2, i64 0, i64 9) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTC7test8_D8_8test8_B2, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTV7test8_D, i64 0, i64 9) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTV7test8_D, i64 0, i64 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTV7test8_D, i64 0, i64 24) to i8*)]
struct test9_B3 { virtual void funcB3(); int i; };
@@ -404,77 +201,7 @@ struct test9_D : virtual test9_B1, virtual test9_B21, virtual test9_B31 {
virtual void funcD() { }
};
-// CHECK-LP64: __ZTV7test9_D:
-// CHECK-LP64-NEXT: .quad 168
-// CHECK-LP64-NEXT: .quad 152
-// CHECK-LP64-NEXT: .quad 136
-// CHECK-LP64-NEXT: .quad 120
-// CHECK-LP64-NEXT: .quad 104
-// CHECK-LP64-NEXT: .quad 88
-// CHECK-LP64-NEXT: .quad 72
-// CHECK-LP64-NEXT: .quad 56
-// CHECK-LP64-NEXT: .quad 40
-// CHECK-LP64-NEXT: .quad 24
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN7test9_D5funcDEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN8test9_B16funcB1Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN8test9_B26funcB2Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551576
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN8test9_B36funcB3Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551560
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN9test9_B217funcB21Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551544
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN9test9_B227funcB22Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551528
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN9test9_B237funcB23Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 64
-// CHECK-LP64-NEXT: .quad 48
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551512
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN9test9_B317funcB31Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551496
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN9test9_B327funcB32Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551480
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN9test9_B337funcB33Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551464
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN10test9_B2328funcB232Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551448
-// CHECK-LP64-NEXT: .quad __ZTI7test9_D
-// CHECK-LP64-NEXT: .quad __ZN10test9_B2318funcB231Ev
+// CHECK-LPLL64:@_ZTV7test9_D = weak_odr constant [70 x i8*] [i8* inttoptr (i64 168 to i8*), i8* inttoptr (i64 152 to i8*), i8* inttoptr (i64 136 to i8*), i8* inttoptr (i64 120 to i8*), i8* inttoptr (i64 104 to i8*), i8* inttoptr (i64 88 to i8*), i8* inttoptr (i64 72 to i8*), i8* inttoptr (i64 56 to i8*), i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 8 to i8*), i8* null, i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.test9_D*)* @_ZN7test9_D5funcDEv to i8*), i8* null, i8* inttoptr (i64 32 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.test9_B1*)* @_ZN8test9_B16funcB1Ev to i8*), i8* null, i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -24 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZN8test9_B26funcB2Ev to i8*), i8* null, i8* inttoptr (i64 -40 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN8test9_B36funcB3Ev to i8*), i8* null, i8* inttoptr (i64 32 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -56 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.test9_B1*)* @_ZN9test9_B217funcB21Ev to i8*), i8* null, i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -72 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZN9test9_B227funcB22Ev to i8*), i8* null, i8* inttoptr (i64 -88 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN9test9_B237funcB23Ev to i8*), i8* null, i8* inttoptr (i64 64 to i8*), i8* inttoptr (i64 48 to i8*), i8* inttoptr (i64 32 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -104 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.test9_B31*)* @_ZN9test9_B317funcB31Ev to i8*), i8* null, i8* inttoptr (i64 32 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -120 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.test9_B1*)* @_ZN9test9_B327funcB32Ev to i8*), i8* null, i8* inttoptr (i64 -136 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN9test9_B337funcB33Ev to i8*), i8* null, i8* inttoptr (i64 -152 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test9_B2328funcB232Ev to i8*), i8* null, i8* inttoptr (i64 -168 to i8*), i8* bitcast (%2* @_ZTI7test9_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test9_B2318funcB231Ev to i8*)] ; <[70 x i8*]*> [#uses=12]
struct test10_O { int i; };
@@ -503,26 +230,7 @@ class test10_D : test10_B1, test10_B2 {
void ftest10_B2aa() { }
};
-// CHECK-LP64:__ZTV8test10_D:
-// CHECK-LP64-NEXT: .quad 40
-// CHECK-LP64-NEXT: .quad 24
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test10_D
-// CHECK-LP64-NEXT: .quad __ZN9test10_B110ftest10_B1Ev
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI8test10_D
-// CHECK-LP64-NEXT: .quad __ZN10test10_B2a11ftest10_B2aEv
-// CHECK-LP64-NEXT: .quad __ZN9test10_B210ftest10_B2Ev
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad __ZTI8test10_D
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad 18446744073709551576
-// CHECK-LP64-NEXT: .quad __ZTI8test10_D
+// CHECK-LPLL64:@_ZTV8test10_D = weak_odr constant [19 x i8*] [i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 16 to i8*), i8* null, i8* bitcast (%1* @_ZTI8test10_D to i8*), i8* bitcast (void (%struct.test10_B1*)* @_ZN9test10_B110ftest10_B1Ev to i8*), i8* inttoptr (i64 32 to i8*), i8* inttoptr (i64 8 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%1* @_ZTI8test10_D to i8*), i8* bitcast (void (%struct.test10_B2a*)* @_ZN10test10_B2a11ftest10_B2aEv to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN9test10_B210ftest10_B2Ev to i8*), i8* inttoptr (i64 -8 to i8*), i8* inttoptr (i64 -24 to i8*), i8* bitcast (%1* @_ZTI8test10_D to i8*), i8* inttoptr (i64 -24 to i8*), i8* inttoptr (i64 -40 to i8*), i8* bitcast (%1* @_ZTI8test10_D to i8*)] ; <[19 x i8*]*> [#uses=4]
struct test11_B {
@@ -537,14 +245,8 @@ struct test11_D : test11_B {
virtual void D2() { }
};
-// CHECK-LP64:__ZTV8test11_D:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test11_D
-// CHECK-LP64-NEXT: .quad __ZN8test11_B2B1Ev
-// CHECK-LP64-NEXT: .quad __ZN8test11_D1DEv
-// CHECK-LP64-NEXT: .quad __ZN8test11_B2B2Ev
-// CHECK-LP64-NEXT: .quad __ZN8test11_D2D1Ev
-// CHECK-LP64-NEXT: .quad __ZN8test11_D2D2Ev
+// CHECK-LPLL64:@_ZTV8test11_D = weak_odr constant [7 x i8*] [i8* null, i8* bitcast (%4* @_ZTI8test11_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test11_B2B1Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test11_D1DEv to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test11_B2B2Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test11_D2D1Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test11_D2D2Ev to i8*)]
+
struct test13_B {
virtual void B1() { }
@@ -583,46 +285,7 @@ struct test13_D : test13_NV1, virtual test13_B2 {
virtual void fooNV1() { }
};
-// CHECK-LP64:__ZTV8test13_D:
-// CHECK-LP64-NEXT: .quad 24
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test13_D
-// CHECK-LP64-NEXT: .quad __ZN8test13_D6fooNV1Ev
-// CHECK-LP64-NEXT: .quad __ZN8test13_D1DEv
-// CHECK-LP64-NEXT: .quad __ZN8test13_D2D1Ev
-// CHECK-LP64-NEXT: .quad __ZN8test13_D2DbEv
-// CHECK-LP64-NEXT: .quad __ZN8test13_D2DdEv
-// CHECK-LP64-NEXT: .quad __ZN8test13_D2D2Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI8test13_D
-// CHECK-LP64-NEXT: .quad __ZN9test13_B23B2aEv
-// CHECK-LP64-NEXT: .quad __ZN9test13_B22B2Ev
-// CHECK-LP64-NEXT: .quad __ZTv0_n48_N8test13_D1DEv
-// CHECK-LP64-NEXT: .quad __ZN9test13_B22DaEv
-// CHECK-LP64-NEXT: .quad __ZTv0_n64_N8test13_D2DdEv
-// CHECK-LP64-NEXT: .quad __ZN9test13_B23B2bEv
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551592
-// CHECK-LP64-NEXT: .quad __ZTI8test13_D
-// CHECK-LP64-NEXT: .quad __ZN8test13_B2B1Ev
-// CHECK-LP64-NEXT: .quad __ZTv0_n32_N8test13_D1DEv
-// CHECK-LP64-NEXT: .quad __ZTv0_n40_N9test13_B22DaEv
-// CHECK-LP64-NEXT: .quad __ZTv0_n48_N8test13_D2DbEv
-// CHECK-LP64-NEXT: .quad __ZN8test13_B2DcEv
-// CHECK-LP64-NEXT: .quad __ZTv0_n64_N9test13_B22B2Ev
+// CHECK-LPLL64:@_ZTV8test13_D = weak_odr constant [39 x i8*] [i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 8 to i8*), i8* null, i8* bitcast (%1* @_ZTI8test13_D to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN8test13_D6fooNV1Ev to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN8test13_D1DEv to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN8test13_D2D1Ev to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN8test13_D2DbEv to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN8test13_D2DdEv to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZN8test13_D2D2Ev to i8*), i8* null, i8* inttoptr (i64 -8 to i8*), i8* null, i8* inttoptr (i64 -8 to i8*), i8* null, i8* null, i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%1* @_ZTI8test13_D to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZN9test13_B23B2aEv to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZN9test13_B22B2Ev to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZTv0_n48_N8test13_D1DEv to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZN9test13_B22DaEv to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZTv0_n64_N8test13_D2DdEv to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZN9test13_B23B2bEv to i8*), i8* inttoptr (i64 -16 to i8*), i8* null, i8* inttoptr (i64 -24 to i8*), i8* inttoptr (i64 -16 to i8*), i8* inttoptr (i64 -24 to i8*), i8* null, i8* inttoptr (i64 -24 to i8*), i8* bitcast (%1* @_ZTI8test13_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN8test13_B2B1Ev to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZTv0_n32_N8test13_D1DEv to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZTv0_n40_N9test13_B22DaEv to i8*), i8* bitcast (void (%struct.test10_B2*)* @_ZTv0_n48_N8test13_D2DbEv to i8*), i8* bitcast (void (%struct.B*)* @_ZN8test13_B2DcEv to i8*), i8* bitcast (void (%struct.test13_B2*)* @_ZTv0_n64_N9test13_B22B2Ev to i8*)]
class test14 {
@@ -662,30 +325,7 @@ struct test15_D : test15_NV1, virtual test15_B2 {
virtual test15_D *foo1() { return 0; }
};
-// CHECK-LP64:__ZTV8test15_D:
-// CHECK-LP64-NEXT: .quad 32
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test15_D
-// CHECK-LP64-NEXT: .quad __ZN10test15_NV16fooNV1Ev
-// CHECK-LP64-NEXT: .quad __ZN8test15_D4foo1Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad __ZTI8test15_D
-// CHECK-LP64-NEXT: .quad __ZN10test15_NV16fooNV1Ev
-// CHECK-LP64-NEXT: .quad __ZTcv0_n40_v0_n24_N8test15_D4foo1Ev
-// CHECK-LP64-NEXT: .quad __ZN9test15_B24foo2Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad 18446744073709551584
-// CHECK-LP64-NEXT: .quad 18446744073709551584
-// CHECK-LP64-NEXT: .quad __ZTI8test15_D
-// CHECK-LP64-NEXT: .quad __ZTcv0_n24_v0_n32_N8test15_D4foo1Ev
-// CHECK-LP64-NEXT: .quad __ZTcv0_n32_v0_n24_N9test15_B24foo2Ev
-// CHECK-LP64-NEXT: .quad __ZN8test15_B4foo3Ev
+// CHECK-LPLL64:@_ZTV8test15_D = weak_odr constant [23 x i8*] [i8* inttoptr (i64 32 to i8*), i8* inttoptr (i64 16 to i8*), i8* null, i8* bitcast (%1* @_ZTI8test15_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test15_NV16fooNV1Ev to i8*), i8* bitcast (%struct.test15_D* (%struct.test15_D*)* @_ZN8test15_D4foo1Ev to i8*), i8* null, i8* inttoptr (i64 -16 to i8*), i8* null, i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -16 to i8*), i8* bitcast (%1* @_ZTI8test15_D to i8*), i8* bitcast (void (%struct.B*)* @_ZN10test15_NV16fooNV1Ev to i8*), i8* bitcast (%struct.test15_D* (%struct.test15_D*)* @_ZTcv0_n40_v0_n24_N8test15_D4foo1Ev to i8*), i8* bitcast (%struct.test15_B2* (%struct.test15_B2*)* @_ZN9test15_B24foo2Ev to i8*), i8* null, i8* inttoptr (i64 -16 to i8*), i8* inttoptr (i64 -32 to i8*), i8* inttoptr (i64 -32 to i8*), i8* bitcast (%1* @_ZTI8test15_D to i8*), i8* bitcast (%struct.test15_D* (%struct.test15_D*)* @_ZTcv0_n24_v0_n32_N8test15_D4foo1Ev to i8*), i8* bitcast (%struct.test15_B2* (%struct.test15_B2*)* @_ZTcv0_n32_v0_n24_N9test15_B24foo2Ev to i8*), i8* bitcast (%struct.B* (%struct.B*)* @_ZN8test15_B4foo3Ev to i8*)]
struct test16_NV1 {
@@ -721,22 +361,23 @@ struct test16_D : test16_NV1, virtual test16_B2 {
virtual test16_D *foo1() { return 0; }
};
+// FIXME:
// CHECK-LP64: __ZTV8test16_D:
// CHECK-LP64-NEXT: .quad 32
// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad 0
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
// CHECK-LP64-NEXT: .quad __ZN10test16_NV16fooNV1Ev
// CHECK-LP64-NEXT: .quad __ZN10test16_NV17foo_NV1Ev
// CHECK-LP64-NEXT: .quad __ZN8test16_D3barEv
// CHECK-LP64-NEXT: .quad __ZN8test16_D4foo1Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad -16
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad 0
// CHECK-LP64-NEXT: .quad 16
-// CHECK-LP64-NEXT: .quad 18446744073709551600
+// CHECK-LP64-NEXT: .quad -16
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
// CHECK-LP64-NEXT: .quad __ZN10test16_NV16fooNV1Ev
// CHECK-LP64-NEXT: .quad __ZN10test16_NV17foo_NV1Ev
@@ -745,13 +386,13 @@ struct test16_D : test16_NV1, virtual test16_B2 {
// CHECK-LP64-NEXT: .quad __ZN9test16_B26foo_B2Ev
// CHECK-LP64-NEXT .quad 16
// CHECK-LP64-NEXT .quad 16
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64: .quad 18446744073709551600
-// CHECK-LP64-NEXT: .quad 18446744073709551584
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551584
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64: .quad -16
+// CHECK-LP64-NEXT: .quad -32
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad -32
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
// CHECK-LP64-NEXT: .quad __ZN10test16_NV16fooNV1Ev
// CHECK-LP64-NEXT: .quad __ZN10test16_NV17foo_NV1Ev
@@ -759,64 +400,13 @@ struct test16_D : test16_NV1, virtual test16_B2 {
// CHECK-LP64-NEXT: .quad __ZTcv0_n48_v0_n24_N9test16_B24foo2Ev
// CHECK-LP64-NEXT: .quad __ZN8test16_B4foo3Ev
// CHECK-LP64-NEXT: .quad __ZN8test16_B5foo_BEv
-// CHECK-LP64-NEXT: .quad 18446744073709551568
+// CHECK-LP64-NEXT: .quad -48
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
// CHECK-LP64-NEXT .quad __ZTcvn16_n40_v16_n32_N8test16_D4foo1Ev
// CHECK-LP64: .quad __ZN10test16_NV27foo_NV2Ev
// CHECK-LP64-NEXT: .quad __ZN10test16_NV28foo_NV2bEv
-// FIXME: This is the wrong thunk, but until these issues are fixed, better
-// than nothing.
-// CHECK-LPLL64:define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*)
-// CHECK-LPLL64: %{{retval|2}} = alloca %class.test8_D*
-// CHECK-LPLL64: %.addr = alloca %class.test8_D*
-// CHECK-LPLL64: store %class.test8_D* %0, %class.test8_D** %.addr
-// CHECK-LPLL64: %{{this|3}} = load %class.test8_D** %.addr
-// CHECK-LPLL64: %{{1|4}} = bitcast %class.test8_D* %{{this|3}} to i8*
-// CHECK-LPLL64: %{{2|5}} = getelementptr inbounds i8* %{{1|4}}, i64 -16
-// CHECK-LPLL64: %{{3|6}} = bitcast i8* %{{2|5}} to %class.test8_D*
-// CHECK-LPLL64: %{{4|7}} = bitcast %class.test8_D* %{{3|6}} to i8*
-// CHECK-LPLL64: %{{5|8}} = bitcast %class.test8_D* %3 to i64**
-// CHECK-LPLL64: %{{vtable|9}} = load i64** %{{5|8}}
-// CHECK-LPLL64: %{{6|10}} = getelementptr inbounds i64* %{{vtable|9}}, i64 -9
-// CHECK-LPLL64: %{{7|11}} = load i64* %{{6|10}}
-// CHECK-LPLL64: %{{8|12}} = getelementptr i8* %{{4|7}}, i64 %{{7|11}}
-// CHECK-LPLL64: %{{9|13}} = bitcast i8* %{{8|12}} to %class.test8_D*
-// CHECK-LPLL64: %{{call|14}} = call %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D* %{{9|13}})
-// CHECK-LPLL64: store %class.test8_D* %{{call|14}}, %class.test8_D** %{{retval|2}}
-// CHECK-LPLL64: %{{10|15}} = load %class.test8_D** %{{retval|2}}
-// CHECK-LPLL64: ret %class.test8_D* %{{10|15}}
-// CHECK-LPLL64:}
-
-// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%{{class.test8_D|.*}}*)
-// CHECK-LPLL64: %{{retval|2}} = alloca %class.test8_D*
-// CHECK-LPLL64: %.addr = alloca %class.test8_D*
-// CHECK-LPLL64: store %class.test8_D* %0, %class.test8_D** %.addr
-// CHECK-LPLL64: %{{this|3}} = load %class.test8_D** %.addr
-// CHECK-LPLL64: %{{call|4}} = call %class.test8_D* @_ZN8test16_D4foo1Ev(%class.test8_D* %{{this|3}})
-// CHECK-LPLL64: %{{1|5}} = icmp ne %class.test8_D* %{{call|4}}, null
-// CHECK-LPLL64: br i1 %{{1|5}}, label %{{2|6}}, label %{{12|17}}
-// CHECK-LPLL64:; <label>:{{2|6}}
-// CHECK-LPLL64: %{{3|7}} = bitcast %class.test8_D* %{{call|4}} to i8*
-// CHECK-LPLL64: %{{4|8}} = getelementptr inbounds i8* %{{3|7}}, i64 16
-// CHECK-LPLL64: %{{5|9}} = bitcast i8* %4 to %class.test8_D*
-// CHECK-LPLL64: %{{6|10}} = bitcast %class.test8_D* %{{5|9}} to i8*
-// CHECK-LPLL64: %{{7|11}} = bitcast %class.test8_D* %{{5|9}} to i64**
-// CHECK-LPLL64: %{{vtable|12}} = load i64** %{{7|11}}
-// CHECK-LPLL64: %{{8|13}} = getelementptr inbounds i64* %vtable, i64 -4
-// CHECK-LPLL64: %{{9|14}} = load i64* %{{8|13}}
-// CHECK-LPLL64: %{{10|15}} = getelementptr i8* %{{6|10}}, i64 %{{9|14}}
-// CHECK-LPLL64: %{{11|16}} = bitcast i8* %{{10|15}} to %class.test8_D*
-// CHECK-LPLL64: br label %{{13|18}}
-// CHECK-LPLL64:; <label>:{{12|17}}
-// CHECK-LPLL64: br label %{{13|18}}
-// CHECK-LPLL64:; <label>:{{13|18}}
-// CHECK-LPLL64: %{{14|19}} = phi %class.test8_D* [ %{{11|16}}, %{{2|6}} ], [ %{{call|4}}, %{{12|17}} ]
-// CHECK-LPLL64: store %class.test8_D* %{{14|19}}, %class.test8_D** %{{retval|2}}
-// CHECK-LPLL64: %{{15|20}} = load %class.test8_D** %{{retval|2}}
-// CHECK-LPLL64: ret %class.test8_D* %{{15|20}}
-// CHECK-LPLL64:}
class test17_B1 {
@@ -834,23 +424,11 @@ class test17_D : public test17_B2 {
};
-// CHECK-LP64:__ZTV8test17_D:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test17_D
-// CHECK-LP64-NEXT: .quad __ZN9test17_B23fooEv
-// CHECK-LP64-NEXT: .quad __ZN8test17_D3barEv
+// CHECK-LPLL64:@_ZTV8test17_D = weak_odr constant [4 x i8*] [i8* null, i8* bitcast (%4* @_ZTI8test17_D to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test17_B23fooEv to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN8test17_D3barEv to i8*)]
-// CHECK-LP64:__ZTV9test17_B2:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI9test17_B2
-// CHECK-LP64-NEXT: .quad __ZN9test17_B23fooEv
-// CHECK-LP64-NEXT: .quad ___cxa_pure_virtual
+// CHECK-LPLL64:@_ZTV9test17_B2 = weak_odr constant [4 x i8*] [i8* null, i8* bitcast (%4* @_ZTI9test17_B2 to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test17_B23fooEv to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*)]
-// CHECK-LP64:__ZTV9test17_B1:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI9test17_B1
-// CHECK-LP64-NEXT: .quad ___cxa_pure_virtual
-// CHECK-LP64-NEXT: .quad __ZN9test17_B13barEv
+// CHECK-LPLL64:@_ZTV9test17_B1 = weak_odr constant [4 x i8*] [i8* null, i8* bitcast (%0* @_ZTI9test17_B1 to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test17_B13barEv to i8*)]
struct test18_NV1 {
@@ -932,47 +510,19 @@ struct test19_D : virtual test19_B4 {
};
-// CHECK-LP64: __ZTV8test19_D:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test19_D
-// CHECK-LP64-NEXT: .quad __ZN9test19_B13fB1Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B26foB1B2Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B36foB1B3Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B46foB1B4Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B23fB2Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B36foB2B3Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B46foB2B4Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B33fB3Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B46foB3B4Ev
-// CHECK-LP64-NEXT: .quad __ZN9test19_B43fB4Ev
+// CHECK-LPLL64:@_ZTV8test19_D = weak_odr constant [28 x i8*] [i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* bitcast (%3* @_ZTI8test19_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test19_B13fB1Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B26foB1B2Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B36foB1B3Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B46foB1B4Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B23fB2Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B36foB2B3Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B46foB2B4Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B33fB3Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B46foB3B4Ev to i8*), i8* bitcast (void (%class.test17_B2*)* @_ZN9test19_B43fB4Ev to i8*)]
+// FIXME:
// CHECK-LP64: __ZTT8test19_D:
-// CHECK-LP64-NEXT: .quad (__ZTV8test19_D) + 144
-// CHECK-LP64-NEXT: .quad (__ZTV8test19_D) + 144
-// CHECK-LP64-NEXT .quad (__ZTV8test19_D) + 144
-// CHECK-LP64-NEXT .quad (__ZTC8test19_D0_9test19_B4) + 136
-// CHECK-LP64-NEXT .quad (__ZTC8test19_D0_9test19_B3) + 104
-// CHECK-LP64-NEXT .quad (__ZTC8test19_D0_9test19_B3) + 104
-// CHECK-LP64-NEXT .quad (__ZTC8test19_D0_9test19_B4) + 136
-// CHECK-LP64-NEXT .quad (__ZTC8test19_D0_9test19_B2) + 88
-// CHECK-LP64-NEXT .quad (__ZTC8test19_D0_9test19_B1) + 24
-
+// CHECK-LP64-NEXT: .quad __ZTV8test19_D+144
+// CHECK-LP64-NEXT: .quad __ZTV8test19_D+144
+// CHECK-LP64-NEXT .quad __ZTV8test19_D+144
+// CHECK-LP64-NEXT .quad __ZTC8test19_D0_9test19_B4+136
+// CHECK-LP64-NEXT .quad __ZTC8test19_D0_9test19_B3+104
+// CHECK-LP64-NEXT .quad __ZTC8test19_D0_9test19_B3+104
+// CHECK-LP64-NEXT .quad __ZTC8test19_D0_9test19_B4+136
+// CHECK-LP64-NEXT .quad __ZTC8test19_D0_9test19_B2+88
+// CHECK-LP64-NEXT .quad __ZTC8test19_D0_9test19_B1+24
class test20_V {
virtual void foo1();
@@ -987,42 +537,22 @@ class test20_B1 : virtual test20_V1 {
class test20_D : public test20_B, public test20_B1 {
};
-// CHECK-LP64: __ZTV8test20_D:
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test20_D
-// CHECK-LP64-NEXT: .quad __ZN8test20_V4foo1Ev
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI8test20_D
-// CHECK-LP64-NEXT: .quad __ZN9test20_V14foo2Ev
-
-// CHECK-LP64: __ZTC8test20_D0_8test20_B:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test20_B
-// CHECK-LP64-NEXT: .quad __ZN8test20_V4foo1Ev
-
-// CHECK-LP64: __ZTC8test20_D8_9test20_B1:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI9test20_B1
-// CHECK-LP64-NEXT: .quad __ZN9test20_V14foo2Ev
+// CHECK-LPLL64:@_ZTV8test20_D = weak_odr constant [11 x i8*] [i8* inttoptr (i64 8 to i8*), i8* null, i8* null, i8* null, i8* bitcast (%1* @_ZTI8test20_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test20_V4foo1Ev to i8*), i8* null, i8* null, i8* inttoptr (i64 -8 to i8*), i8* bitcast (%1* @_ZTI8test20_D to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test20_V14foo2Ev to i8*)]
+
+// CHECK-LPLL64:@_ZTC8test20_D0_8test20_B = internal constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (%3* @_ZTI8test20_B to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test20_V4foo1Ev to i8*)]
+
+// CHECK-LPLL64:@_ZTC8test20_D8_9test20_B1 = internal constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (%3* @_ZTI9test20_B1 to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test20_V14foo2Ev to i8*)] ; <[5 x i8*]*> [#uses=1]
+// FIXME:
// CHECK-LP64: __ZTT8test20_D:
-// CHECK-LP64-NEXT: .quad (__ZTV8test20_D) + 40
-// CHECK-LP64-NEXT: .quad (__ZTC8test20_D0_8test20_B) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC8test20_D0_8test20_B) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC8test20_D8_9test20_B1) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC8test20_D8_9test20_B1) + 32
-// CHECK-LP64-NEXT .quad (__ZTV8test20_D) + 40
-// CHECK-LP64-NEXT .quad (__ZTV8test20_D) + 80
-// CHECK-LP64-NEXT .quad (__ZTV8test20_D) + 80
+// CHECK-LP64-NEXT: .quad __ZTV8test20_D+40
+// CHECK-LP64-NEXT: .quad __ZTC8test20_D0_8test20_B+32
+// CHECK-LP64-NEXT: .quad __ZTC8test20_D0_8test20_B+32
+// CHECK-LP64-NEXT: .quad __ZTC8test20_D8_9test20_B1+32
+// CHECK-LP64-NEXT: .quad __ZTC8test20_D8_9test20_B1+32
+// CHECK-LP64-NEXT .quad __ZTV8test20_D+40
+// CHECK-LP64-NEXT .quad __ZTV8test20_D+80
+// CHECK-LP64-NEXT .quad __ZTV8test20_D+80
class test21_V {
@@ -1039,45 +569,73 @@ class test21_D : public test21_B, public test21_B1 {
void foo() { }
};
-// CHECK-LP64: __ZTV8test21_D:
-// CHECK-LP64-NEXT: .quad 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test21_D
-// CHECK-LP64-NEXT: .quad __ZN8test21_D3fooEv
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad 18446744073709551608
-// CHECK-LP64-NEXT: .quad __ZTI8test21_D
-// CHECK-LP64-NEXT: .quad __ZTv0_n24_N8test21_D3fooEv
-
-// CHECK-LP64: __ZTC8test21_D0_8test21_B:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI8test21_B
-// CHECK-LP64-NEXT: .quad __ZN8test21_V3fooEv
-
-// CHECK-LP64: __ZTC8test21_D8_9test21_B1:
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad __ZTI9test21_B1
-// CHECK-LP64-NEXT: .quad __ZN9test21_V13fooEv
+// CHECK-LPLL64:@_ZTV8test21_D = weak_odr constant [11 x i8*] [i8* inttoptr (i64 8 to i8*), i8* null, i8* null, i8* null, i8* bitcast (%1* @_ZTI8test21_D to i8*), i8* bitcast (void (%class.test20_D*)* @_ZN8test21_D3fooEv to i8*), i8* null, i8* inttoptr (i64 -8 to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%1* @_ZTI8test21_D to i8*), i8* bitcast (void (%class.test20_D*)* @_ZTv0_n24_N8test21_D3fooEv to i8*)]
+// CHECK-LPLL64:@_ZTC8test21_D0_8test21_B = internal constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (%3* @_ZTI8test21_B to i8*), i8* bitcast (void (%class.test14*)* @_ZN8test21_V3fooEv to i8*)]
+
+// CHECK-LPLL64:@_ZTC8test21_D8_9test21_B1 = internal constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (%3* @_ZTI9test21_B1 to i8*), i8* bitcast (void (%class.test14*)* @_ZN9test21_V13fooEv to i8*)] ; <[5 x i8*]*> [#uses=1]
+
+// FIXME:
// CHECK-LP64: __ZTT8test21_D:
-// CHECK-LP64-NEXT: .quad (__ZTV8test21_D) + 40
-// CHECK-LP64-NEXT: .quad (__ZTC8test21_D0_8test21_B) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC8test21_D0_8test21_B) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC8test21_D8_9test21_B1) + 32
-// CHECK-LP64-NEXT: .quad (__ZTC8test21_D8_9test21_B1) + 32
-// CHECK-LP64-NEXT .quad (__ZTV8test21_D) + 40
-// CHECK-LP64-NEXT .quad (__ZTV8test21_D) + 80
-// CHECK-LP64-NEXT .quad (__ZTV8test21_D) + 80
+// CHECK-LP64-NEXT: .quad __ZTV8test21_D+40
+// CHECK-LP64-NEXT: .quad __ZTC8test21_D0_8test21_B+32
+// CHECK-LP64-NEXT: .quad __ZTC8test21_D0_8test21_B+32
+// CHECK-LP64-NEXT: .quad __ZTC8test21_D8_9test21_B1+32
+// CHECK-LP64-NEXT: .quad __ZTC8test21_D8_9test21_B1+32
+// CHECK-LP64-NEXT .quad __ZTV8test21_D+40
+// CHECK-LP64-NEXT .quad __ZTV8test21_D+80
+// CHECK-LP64-NEXT .quad __ZTV8test21_D+80
+
+
+struct test22_s1 { virtual void dtor() { } };
+struct test22_s2 { virtual void dtor() { } };
+struct test22_s3 : test22_s1, test22_s2 { virtual void dtor() { } };
+struct test22_D : test22_s3 { virtual void dtor() { } };
+
+// CHECK-LPLL64:@_ZTV8test22_D = weak_odr constant [6 x i8*] [i8* null, i8* bitcast (%4* @_ZTI8test22_D to i8*), i8* bitcast (void (%class.test20_D*)* @_ZN8test22_D4dtorEv to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%4* @_ZTI8test22_D to i8*), i8* bitcast (void (%class.test20_D*)* @_ZThn8_N8test22_D4dtorEv to i8*)]
+
+
+class test23_s1 {
+ virtual void fun1(char *t) { }
+};
+class test23_s2 {
+ virtual void fun2(char *t) { }
+};
+class test23_s3 {
+ virtual void fun3(char *t) { }
+};
+class test23_s4: virtual test23_s1, test23_s2, test23_s3 {
+ virtual void fun4(char *t) { }
+};
+class test23_D: virtual test23_s4 {
+ virtual void fun5(char *t) { }
+};
+
+// FIXME:
+// CHECK-LP64: __ZTV8test23_D:
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad 8
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64-NEXT: .quad __ZTI8test23_D
+// CHECK-LP64-NEXT: .quad __ZN9test23_s14fun1EPc
+// CHECK-LP64-NEXT: .quad __ZN8test23_D4fun5EPc
+// CHECK-LP64-NEXT .quad 8
+// CHECK-LP64: .quad 0
+// CHECK-LP64-NEXT: .quad 0
+// CHECK-LP64: .quad -8
+// CHECK-LP64-NEXT: .quad -8
+// CHECK-LP64-NEXT: .quad __ZTI8test23_D
+// CHECK-LP64-NEXT: .quad __ZN9test23_s24fun2EPc
+// CHECK-LP64-NEXT: .quad __ZN9test23_s44fun4EPc
+// CHECK-LP64-NEXT: .quad -16
+// CHECK-LP64-NEXT: .quad __ZTI8test23_D
+// CHECK-LP64-NEXT: .quad __ZN9test23_s34fun3EPc
+test23_D d23;
+test22_D d22;
test21_D d21;
test20_D d20;
test19_D d19;
@@ -1097,3 +655,93 @@ test3_D d3;
test6_D d6;
test7_D d7;
+
+
+int j;
+void *vp;
+void test2() {
+ F f;
+ static int sz = (char *)(&f.f) - (char *)(&f);
+ vp = &sz;
+ j = sz;
+ // FIXME: These should result in a frontend constant a la fold, no run time
+ // initializer
+ // CHECK-LPLL64: define void @_Z5test2v()
+ // CHECK-LPLL64: = getelementptr inbounds %class.F* %f, i32 0, i32 1
+}
+
+static_assert(sizeof(F) == sizeof(void*)*4, "invalid vbase size");
+
+
+void test12_foo() {
+ test12_pa->foo0();
+ test12_pb->foo0();
+ test12_pd->foo0();
+ test12_pa->foo();
+ test12_pb->foo();
+ test12_pd->foo();
+ test12_pa->test12_A::foo();
+}
+
+
+// CHECK-LPLL64:define void @_Z10test12_foov() nounwind {
+// CHECK-LPLL64: call void %
+// CHECK-LPLL64: call void %
+// CHECK-LPLL64: call void %
+// CHECK-LPLL64: call void %
+// CHECK-LPLL64: call void %
+// CHECK-LPLL64: call void %
+// CHECK-LPLL64: call void @_ZN8test12_A3fooEv(%class.test14* %{{.*}})
+
+
+// FIXME: This is the wrong thunk, but until these issues are fixed, better
+// than nothing.
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*)
+// CHECK-LPLL64: %{{retval|2}} = alloca %class.test8_D*
+// CHECK-LPLL64: %.addr = alloca %class.test8_D*
+// CHECK-LPLL64: store %class.test8_D* %0, %class.test8_D** %.addr
+// CHECK-LPLL64: %{{this|3}} = load %class.test8_D** %.addr
+// CHECK-LPLL64: %{{1|4}} = bitcast %class.test8_D* %{{this|3}} to i8*
+// CHECK-LPLL64: %{{2|5}} = getelementptr inbounds i8* %{{1|4}}, i64 -16
+// CHECK-LPLL64: %{{3|6}} = bitcast i8* %{{2|5}} to %class.test8_D*
+// CHECK-LPLL64: %{{4|7}} = bitcast %class.test8_D* %{{3|6}} to i8*
+// CHECK-LPLL64: %{{5|8}} = bitcast %class.test8_D* %3 to i64**
+// CHECK-LPLL64: %{{vtable|9}} = load i64** %{{5|8}}
+// CHECK-LPLL64: %{{6|10}} = getelementptr inbounds i64* %{{vtable|9}}, i64 -9
+// CHECK-LPLL64: %{{7|11}} = load i64* %{{6|10}}
+// CHECK-LPLL64: %{{8|12}} = getelementptr i8* %{{4|7}}, i64 %{{7|11}}
+// CHECK-LPLL64: %{{9|13}} = bitcast i8* %{{8|12}} to %class.test8_D*
+// CHECK-LPLL64: %{{call|14}} = call %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D* %{{9|13}})
+// CHECK-LPLL64: store %class.test8_D* %{{call|14}}, %class.test8_D** %{{retval|2}}
+// CHECK-LPLL64: %{{10|15}} = load %class.test8_D** %{{retval|2}}
+// CHECK-LPLL64: ret %class.test8_D* %{{10|15}}
+// CHECK-LPLL64:}
+
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%{{class.test8_D|.*}}*)
+// CHECK-LPLL64: %{{retval|2}} = alloca %class.test8_D*
+// CHECK-LPLL64: %.addr = alloca %class.test8_D*
+// CHECK-LPLL64: store %class.test8_D* %0, %class.test8_D** %.addr
+// CHECK-LPLL64: %{{this|3}} = load %class.test8_D** %.addr
+// CHECK-LPLL64: %{{call|4}} = call %class.test8_D* @_ZN8test16_D4foo1Ev(%class.test8_D* %{{this|3}})
+// CHECK-LPLL64: %{{1|5}} = icmp ne %class.test8_D* %{{call|4}}, null
+// CHECK-LPLL64: br i1 %{{1|5}}, label %{{2|6}}, label %{{12|17}}
+// CHECK-LPLL64:; <label>:{{2|6}}
+// CHECK-LPLL64: %{{3|7}} = bitcast %class.test8_D* %{{call|4}} to i8*
+// CHECK-LPLL64: %{{4|8}} = getelementptr inbounds i8* %{{3|7}}, i64 16
+// CHECK-LPLL64: %{{5|9}} = bitcast i8* %4 to %class.test8_D*
+// CHECK-LPLL64: %{{6|10}} = bitcast %class.test8_D* %{{5|9}} to i8*
+// CHECK-LPLL64: %{{7|11}} = bitcast %class.test8_D* %{{5|9}} to i64**
+// CHECK-LPLL64: %{{vtable|12}} = load i64** %{{7|11}}
+// CHECK-LPLL64: %{{8|13}} = getelementptr inbounds i64* %vtable, i64 -4
+// CHECK-LPLL64: %{{9|14}} = load i64* %{{8|13}}
+// CHECK-LPLL64: %{{10|15}} = getelementptr i8* %{{6|10}}, i64 %{{9|14}}
+// CHECK-LPLL64: %{{11|16}} = bitcast i8* %{{10|15}} to %class.test8_D*
+// CHECK-LPLL64: br label %{{13|18}}
+// CHECK-LPLL64:; <label>:{{12|17}}
+// CHECK-LPLL64: br label %{{13|18}}
+// CHECK-LPLL64:; <label>:{{13|18}}
+// CHECK-LPLL64: %{{14|19}} = phi %class.test8_D* [ %{{11|16}}, %{{2|6}} ], [ %{{call|4}}, %{{12|17}} ]
+// CHECK-LPLL64: store %class.test8_D* %{{14|19}}, %class.test8_D** %{{retval|2}}
+// CHECK-LPLL64: %{{15|20}} = load %class.test8_D** %{{retval|2}}
+// CHECK-LPLL64: ret %class.test8_D* %{{15|20}}
+// CHECK-LPLL64:}
diff --git a/test/CodeGenCXX/vtt-layout.cpp b/test/CodeGenCXX/vtt-layout.cpp
new file mode 100644
index 000000000000..d7d4227ed01d
--- /dev/null
+++ b/test/CodeGenCXX/vtt-layout.cpp
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+// Test1::B should just have a single entry in its VTT, which points to the vtable.
+namespace Test1 {
+struct A { };
+
+struct B : virtual A {
+ virtual void f();
+};
+
+void B::f() { }
+}
+
+// Check that we don't add a secondary virtual pointer for Test2::A, since Test2::A doesn't have any virtual member functions or bases.
+namespace Test2 {
+ struct A { };
+
+ struct B : A { virtual void f(); };
+ struct C : virtual B { };
+
+ C c;
+}
+
+// This is the sample from the C++ Itanium ABI, p2.6.2.
+namespace Test3 {
+ class A1 { int i; };
+ class A2 { int i; virtual void f(); };
+ class V1 : public A1, public A2 { int i; };
+ class B1 { int i; };
+ class B2 { int i; };
+ class V2 : public B1, public B2, public virtual V1 { int i; };
+ class V3 {virtual void g(); };
+ class C1 : public virtual V1 { int i; };
+ class C2 : public virtual V3, virtual V2 { int i; };
+ class X1 { int i; };
+ class C3 : public X1 { int i; };
+ class D : public C1, public C2, public C3 { int i; };
+
+ D d;
+}
+
+// This is the sample from the C++ Itanium ABI, p2.6.2, with the change suggested
+// (making A2 a virtual base of V1)
+namespace Test4 {
+ class A1 { int i; };
+ class A2 { int i; virtual void f(); };
+ class V1 : public A1, public virtual A2 { int i; };
+ class B1 { int i; };
+ class B2 { int i; };
+ class V2 : public B1, public B2, public virtual V1 { int i; };
+ class V3 {virtual void g(); };
+ class C1 : public virtual V1 { int i; };
+ class C2 : public virtual V3, virtual V2 { int i; };
+ class X1 { int i; };
+ class C3 : public X1 { int i; };
+ class D : public C1, public C2, public C3 { int i; };
+
+ D d;
+}
+
+// CHECK: @_ZTTN5Test11BE = constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*]* @_ZTVN5Test11BE, i64 0, i64 3) to i8*)]
+// CHECK: @_ZTTN5Test41DE = weak_odr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 10) to i8*)] ; <[19 x i8*]*> [#uses=4]
+// CHECK: @_ZTTN5Test31DE = weak_odr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 6) to i8*)] ; <[13 x i8*]*> [#uses=3]
+// CHECK: @_ZTTN5Test21CE = weak_odr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*)] ; <[2 x i8*]*> [#uses=0]
diff --git a/test/Driver/darwin-arm.c b/test/Driver/darwin-arm.c
deleted file mode 100644
index 330918dd47d0..000000000000
--- a/test/Driver/darwin-arm.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang -ccc-host-triple i386-apple-darwin9 -arch arm -print-search-dirs | FileCheck %s
-
-// Check that we look in the relative libexec directory.
-// CHECK: {{programs: =.*/../libexec:}}
diff --git a/test/FixIt/typo.m b/test/FixIt/typo.m
index 4c3ee5f60bc8..c2069dd4169d 100644
--- a/test/FixIt/typo.m
+++ b/test/FixIt/typo.m
@@ -12,6 +12,7 @@ void test() {
}
@protocol P1
+@optional
@property int *sprop; // expected-note{{'sprop' declared here}}
@end
diff --git a/test/Index/Inputs/remap-load-to.c b/test/Index/Inputs/remap-load-to.c
new file mode 100644
index 000000000000..8f9e1eba478a
--- /dev/null
+++ b/test/Index/Inputs/remap-load-to.c
@@ -0,0 +1,3 @@
+int foo(int parm1, float parm2) {
+ return parm1 + parm2;
+}
diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m
index fb97de15b11a..f9627123a0de 100644
--- a/test/Index/TestClassDecl.m
+++ b/test/Index/TestClassDecl.m
@@ -16,23 +16,18 @@ void function(Foo * arg)
}
// CHECK-scan: {start_line=1 start_col=1 end_line=7 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK-scan: {start_line=8 start_col=1 end_line=8 end_col=7} Invalid Cursor => NotImplemented
-// CHECK-scan: {start_line=8 start_col=8 end_line=8 end_col=10} ObjCClassRef=Foo:8:1
+// CHECK-scan: {start_line=8 start_col=1 end_line=8 end_col=7} UnexposedDecl=:8:1
+// CHECK-scan: {start_line=8 start_col=8 end_line=8 end_col=10} ObjCClassRef=Foo:10:12
// CHECK-scan: {start_line=8 start_col=11 end_line=9 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK-scan: {start_line=10 start_col=1 end_line=11 end_col=4} ObjCInterfaceDecl=Foo:10:1
-// CHECK-scan: {start_line=11 start_col=5 end_line=12 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK-scan: {start_line=13 start_col=1 end_line=13 end_col=4} FunctionDecl=function:13:6
-// CHECK-scan: {start_line=13 start_col=5 end_line=13 end_col=5} Invalid Cursor => NoDeclFound
-// CHECK-scan: {start_line=13 start_col=6 end_line=13 end_col=14} FunctionDecl=function:13:6
-// CHECK-scan: {start_line=13 start_col=15 end_line=13 end_col=17} ObjCClassRef=Foo:13:21
-// CHECK-scan: {start_line=13 start_col=18 end_line=13 end_col=18} FunctionDecl=function:13:6
-// CHECK-scan: {start_line=13 start_col=19 end_line=13 end_col=19} ParmDecl=arg:13:21
-// CHECK-scan: {start_line=13 start_col=20 end_line=13 end_col=20} FunctionDecl=function:13:6
-// CHECK-scan: {start_line=13 start_col=21 end_line=13 end_col=23} ParmDecl=arg:13:21
-// CHECK-scan: {start_line=13 start_col=24 end_line=16 end_col=1} FunctionDecl=function:13:6
-// CHECK-scan: {start_line=16 start_col=2 end_line=38 end_col=1} Invalid Cursor => NoDeclFound
+// CHECK-scan: {start_line=10 start_col=1 end_line=11 end_col=4} ObjCInterfaceDecl=Foo:10:12
+// CHECK-scan: {start_line=11 start_col=5 end_line=13 end_col=5} Invalid Cursor => NoDeclFound
+// CHECK-scan: {start_line=13 start_col=6 end_line=13 end_col=14} FunctionDecl=function:13:6 (Definition)
+// CHECK-scan: {start_line=13 start_col=15 end_line=13 end_col=17} ObjCClassRef=Foo:10:12
+// CHECK-scan: {start_line=13 start_col=18 end_line=13 end_col=23} ParmDecl=arg:13:21 (Definition)
+// CHECK-scan: {start_line=13 start_col=24 end_line=13 end_col=25} FunctionDecl=function:13:6 (Definition)
+// CHECK-scan: {start_line=14 start_col=1 end_line=16 end_col=1} UnexposedStmt=function
-// CHECK-load: TestClassDecl.m:10:12: ObjCInterfaceDecl=Foo:10:1 [Context=TestClassDecl.m] [Extent=10:1:11:4]
-// CHECK-load: TestClassDecl.m:13:6: FunctionDefn=function [Context=TestClassDecl.m] [Extent=13:6:16:1]
-// CHECK-load: TestClassDecl.m:13:21: ParmDecl=arg:13:21 [Context=function] [Extent=13:21:13:23]
+// CHECK-load: TestClassDecl.m:10:12: ObjCInterfaceDecl=Foo:10:12 [Extent=10:1:11:4]
+// CHECK-load: TestClassDecl.m:13:6: FunctionDecl=function:13:6 (Definition) [Extent=13:6:16:1]
+// CHECK-load: TestClassDecl.m:13:21: ParmDecl=arg:13:21 (Definition) [Extent=13:15:13:23]
diff --git a/test/Index/TestClassForwardDecl.m b/test/Index/TestClassForwardDecl.m
index e795972a7d13..c53453b0ba89 100644
--- a/test/Index/TestClassForwardDecl.m
+++ b/test/Index/TestClassForwardDecl.m
@@ -13,19 +13,14 @@ void function(Foo * arg)
}
// CHECK-scan: {start_line=1 start_col=1 end_line=7 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK-scan: {start_line=8 start_col=1 end_line=8 end_col=7} Invalid Cursor => NotImplemented
-// CHECK-scan: {start_line=8 start_col=8 end_line=8 end_col=10} ObjCClassRef=Foo:8:1
-// CHECK-scan: {start_line=8 start_col=11 end_line=9 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK-scan: {start_line=10 start_col=1 end_line=10 end_col=4} FunctionDecl=function:10:6
-// CHECK-scan: {start_line=10 start_col=5 end_line=10 end_col=5} Invalid Cursor => NoDeclFound
-// CHECK-scan: {start_line=10 start_col=6 end_line=10 end_col=14} FunctionDecl=function:10:6
-// CHECK-scan: {start_line=10 start_col=15 end_line=10 end_col=17} ObjCClassRef=Foo:10:21
-// CHECK-scan: {start_line=10 start_col=18 end_line=10 end_col=18} FunctionDecl=function:10:6
-// CHECK-scan: {start_line=10 start_col=19 end_line=10 end_col=19} ParmDecl=arg:10:21
-// CHECK-scan: {start_line=10 start_col=20 end_line=10 end_col=20} FunctionDecl=function:10:6
-// CHECK-scan: {start_line=10 start_col=21 end_line=10 end_col=23} ParmDecl=arg:10:21
-// CHECK-scan: {start_line=10 start_col=24 end_line=13 end_col=1} FunctionDecl=function:10:6
-// CHECK-scan: {start_line=13 start_col=2 end_line=46 end_col=1} Invalid Cursor => NoDeclFound
+// CHECK-scan: {start_line=8 start_col=1 end_line=8 end_col=7} UnexposedDecl=:8:1
+// CHECK-scan: {start_line=8 start_col=8 end_line=8 end_col=10} ObjCClassRef=Foo:8:8
+// CHECK-scan: {start_line=8 start_col=11 end_line=10 end_col=5} Invalid Cursor => NoDeclFound
+// CHECK-scan: {start_line=10 start_col=6 end_line=10 end_col=14} FunctionDecl=function:10:6 (Definition)
+// CHECK-scan: {start_line=10 start_col=15 end_line=10 end_col=17} ObjCClassRef=Foo:8:8
+// CHECK-scan: {start_line=10 start_col=18 end_line=10 end_col=23} ParmDecl=arg:10:21 (Definition)
+// CHECK-scan: {start_line=10 start_col=24 end_line=10 end_col=25} FunctionDecl=function:10:6 (Definition)
+// CHECK-scan: {start_line=11 start_col=1 end_line=13 end_col=1} UnexposedStmt=function
@@ -41,6 +36,6 @@ void function(Foo * arg)
-// CHECK-load: TestClassForwardDecl.m:10:6: FunctionDefn=function [Context=TestClassForwardDecl.m]
-// CHECK-load: TestClassForwardDecl.m:10:21: ParmDecl=arg:10:21 [Context=function]
+// CHECK-load: TestClassForwardDecl.m:10:6: FunctionDecl=function:10:6 (Definition)
+// CHECK-load: TestClassForwardDecl.m:10:21: ParmDecl=arg:10:21
diff --git a/test/Index/c-index-api-fn-scan.m b/test/Index/c-index-api-fn-scan.m
deleted file mode 100644
index 8cbc036a5ca2..000000000000
--- a/test/Index/c-index-api-fn-scan.m
+++ /dev/null
@@ -1,217 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast
-// RUN: c-index-test -test-load-tu %t.ast scan-function | FileCheck %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@interface Foo
-{
-}
-
-- foo;
-+ fooC;
-
-@end
-
-@interface Bar : Foo
-{
-}
-
-@end
-
-@interface Foo (FooCat)
-- (int) catMethodWithFloat:(float) fArg;
-- (float) floatMethod;
-@end
-
-@protocol Proto
-- pMethod;
-@end
-
-@protocol SubP <Proto>
-- spMethod;
-@end
-
-@interface Baz : Bar <SubP>
-{
- int _anIVar;
-}
-
-- (Foo *) bazMethod;
-
-@end
-
-enum {
- someEnum
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-int main (int argc, const char * argv[]) {
- Baz * bee;
- id a = [bee foo];
- id <SubP> c = [Foo fooC];
- id <Proto> d;
- d = c;
- [d pMethod];
- [bee catMethodWithFloat:[bee floatMethod]];
- main(someEnum, (const char **)bee);
-}
-
-// CHECK: c-index-api-fn-scan.m:84:2: ObjCClassRef=Baz:84:8 [Context:Baz]
-// CHECK: c-index-api-fn-scan.m:84:3: ObjCClassRef=Baz:84:8 [Context:Baz]
-// CHECK: c-index-api-fn-scan.m:84:4: ObjCClassRef=Baz:84:8 [Context:Baz]
-// CHECK: c-index-api-fn-scan.m:84:6: VarDecl=bee:84:8 [Context:bee]
-// CHECK: c-index-api-fn-scan.m:84:8: VarDecl=bee:84:8 [Context:bee]
-// CHECK: c-index-api-fn-scan.m:84:9: VarDecl=bee:84:8 [Context:bee]
-// CHECK: c-index-api-fn-scan.m:84:10: VarDecl=bee:84:8 [Context:bee]
-// CHECK: <invalid loc>:85:2: TypedefDecl=id:0:0 [Context:id]
-// CHECK: <invalid loc>:85:3: TypedefDecl=id:0:0 [Context:id]
-// CHECK: c-index-api-fn-scan.m:85:5: VarDecl=a:85:5 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:6: VarDecl=a:85:5 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:7: VarDecl=a:85:5 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:8: VarDecl=a:85:5 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:9: ObjCSelectorRef=foo:24:1 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:10: VarRef=bee:84:8 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:11: VarRef=bee:84:8 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:12: VarRef=bee:84:8 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:13: ObjCSelectorRef=foo:24:1 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:14: ObjCSelectorRef=foo:24:1 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:15: ObjCSelectorRef=foo:24:1 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:16: ObjCSelectorRef=foo:24:1 [Context:a]
-// CHECK: c-index-api-fn-scan.m:85:17: ObjCSelectorRef=foo:24:1 [Context:a]
-// CHECK: <invalid loc>:86:2: TypedefDecl=id:0:0 [Context:id]
-// CHECK: <invalid loc>:86:3: TypedefDecl=id:0:0 [Context:id]
-// CHECK: c-index-api-fn-scan.m:86:5: VarDecl=c:86:12 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:6: ObjCProtocolRef=SubP:86:12 [Context:SubP]
-// CHECK: c-index-api-fn-scan.m:86:7: ObjCProtocolRef=SubP:86:12 [Context:SubP]
-// CHECK: c-index-api-fn-scan.m:86:8: ObjCProtocolRef=SubP:86:12 [Context:SubP]
-// CHECK: c-index-api-fn-scan.m:86:9: ObjCProtocolRef=SubP:86:12 [Context:SubP]
-// CHECK: c-index-api-fn-scan.m:86:10: VarDecl=c:86:12 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:12: VarDecl=c:86:12 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:13: VarDecl=c:86:12 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:14: VarDecl=c:86:12 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:15: VarDecl=c:86:12 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:16: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:17: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:18: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:19: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:20: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:21: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:22: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:23: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:24: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: c-index-api-fn-scan.m:86:25: ObjCSelectorRef=fooC:25:1 [Context:c]
-// CHECK: <invalid loc>:87:2: TypedefDecl=id:0:0 [Context:id]
-// CHECK: <invalid loc>:87:3: TypedefDecl=id:0:0 [Context:id]
-// CHECK: c-index-api-fn-scan.m:87:5: VarDecl=d:87:13 [Context:d]
-// CHECK: c-index-api-fn-scan.m:87:6: ObjCProtocolRef=Proto:87:13 [Context:Proto]
-// CHECK: c-index-api-fn-scan.m:87:7: ObjCProtocolRef=Proto:87:13 [Context:Proto]
-// CHECK: c-index-api-fn-scan.m:87:8: ObjCProtocolRef=Proto:87:13 [Context:Proto]
-// CHECK: c-index-api-fn-scan.m:87:9: ObjCProtocolRef=Proto:87:13 [Context:Proto]
-// CHECK: c-index-api-fn-scan.m:87:10: ObjCProtocolRef=Proto:87:13 [Context:Proto]
-// CHECK: c-index-api-fn-scan.m:87:11: VarDecl=d:87:13 [Context:d]
-// CHECK: c-index-api-fn-scan.m:87:13: VarDecl=d:87:13 [Context:d]
-// CHECK: c-index-api-fn-scan.m:88:2: VarRef=d:87:13 [Context:main]
-// CHECK: c-index-api-fn-scan.m:88:6: VarRef=c:86:12 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:2: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:3: VarRef=d:87:13 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:4: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:5: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:6: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:7: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:8: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:9: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:10: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:11: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:89:12: ObjCSelectorRef=pMethod:41:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:2: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:3: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:4: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:5: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:6: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:7: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:8: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:9: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:10: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:11: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:12: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:13: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:14: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:15: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:16: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:17: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:18: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:19: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:20: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:21: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:22: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:23: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:24: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:25: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:26: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:27: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:28: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:29: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:30: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:31: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:32: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:33: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:34: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:35: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:36: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:37: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:38: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:39: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:40: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:41: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:42: ObjCSelectorRef=floatMethod:37:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:90:43: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:3: FunctionRef=main:83:5 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:4: FunctionRef=main:83:5 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:5: FunctionRef=main:83:5 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:6: FunctionRef=main:83:5 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:8: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:9: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:10: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:11: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:12: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:13: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:14: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:15: EnumConstantRef=someEnum:58:3 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:33: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:34: VarRef=bee:84:8 [Context:main]
-// CHECK: c-index-api-fn-scan.m:91:35: VarRef=bee:84:8 [Context:main]
diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m
index 8a1e4d1556e4..cf0dbff457a1 100644
--- a/test/Index/c-index-api-loadTU-test.m
+++ b/test/Index/c-index-api-loadTU-test.m
@@ -53,33 +53,79 @@ int main (int argc, const char * argv[]) {
main(someEnum, (const char **)bee);
}
-// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:1 [Context=c-index-api-loadTU-test.m] [Extent=4:1:11:4]
-// CHECK: c-index-api-loadTU-test.m:8:1: ObjCInstanceMethodDecl=foo:8:1 [Context=Foo] [Extent=8:1:8:6]
-// CHECK: c-index-api-loadTU-test.m:9:1: ObjCClassMethodDecl=fooC:9:1 [Context=Foo] [Extent=9:1:9:7]
-// CHECK: c-index-api-loadTU-test.m:13:12: ObjCInterfaceDecl=Bar:13:1 [Context=c-index-api-loadTU-test.m] [Extent=13:1:17:4]
-// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:13:1 [Context=Bar] [Extent=13:1:17:4]
-// CHECK: c-index-api-loadTU-test.m:19:1: ObjCCategoryDecl=FooCat:19:1 [Context=c-index-api-loadTU-test.m] [Extent=19:1:22:4]
-// CHECK: c-index-api-loadTU-test.m:4:1: ObjCClassRef=Foo:19:1 [Context=FooCat] [Extent=19:1:22:4]
-// CHECK: c-index-api-loadTU-test.m:20:1: ObjCInstanceMethodDecl=catMethodWithFloat::20:1 [Context=FooCat] [Extent=20:1:20:40]
-// CHECK: c-index-api-loadTU-test.m:21:1: ObjCInstanceMethodDecl=floatMethod:21:1 [Context=FooCat] [Extent=21:1:21:22]
-// CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolDecl=Proto:24:1 [Context=c-index-api-loadTU-test.m] [Extent=24:1:26:4]
-// CHECK: c-index-api-loadTU-test.m:25:1: ObjCInstanceMethodDecl=pMethod:25:1 [Context=Proto] [Extent=25:1:25:10]
-// CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolDecl=SubP:28:1 [Context=c-index-api-loadTU-test.m] [Extent=28:1:30:4]
-// CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolRef=Proto:24:1 [Context=SubP] [Extent=24:1:26:4]
-// CHECK: c-index-api-loadTU-test.m:29:1: ObjCInstanceMethodDecl=spMethod:29:1 [Context=SubP] [Extent=29:1:29:11]
-// CHECK: c-index-api-loadTU-test.m:32:12: ObjCInterfaceDecl=Baz:32:1 [Context=c-index-api-loadTU-test.m] [Extent=32:1:39:4]
-// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:32:1 [Context=Baz] [Extent=32:1:39:4]
-// CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolRef=SubP:28:1 [Context=Baz] [Extent=28:1:30:4]
-// CHECK: c-index-api-loadTU-test.m:34:9: ObjCIvarDecl=_anIVar:34:9 [Context=Baz] [Extent=34:9:34:15]
-// CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=bazMethod:37:1 [Context=Baz] [Extent=37:1:37:20]
-// CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 [Context=c-index-api-loadTU-test.m] [Extent=41:1:43:1]
-// CHECK: c-index-api-loadTU-test.m:42:3: EnumConstantDecl=someEnum:42:3 [Context=] [Extent=42:3:42:10]
-// CHECK: c-index-api-loadTU-test.m:45:5: FunctionDefn=main [Context=c-index-api-loadTU-test.m] [Extent=45:5:54:1]
-// CHECK: c-index-api-loadTU-test.m:45:15: ParmDecl=argc:45:15 [Context=main] [Extent=45:15:45:18]
-// CHECK: c-index-api-loadTU-test.m:45:34: ParmDecl=argv:45:34 [Context=main] [Extent=45:34:45:37]
-// CHECK: c-index-api-loadTU-test.m:46:8: VarDecl=bee:46:8 [Context=main] [Extent=46:8:46:10]
-// CHECK: c-index-api-loadTU-test.m:47:5: VarDecl=a:47:5 [Context=main] [Extent=47:5:47:17]
-// CHECK: c-index-api-loadTU-test.m:48:12: VarDecl=c:48:12 [Context=main] [Extent=48:12:48:25]
-// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 [Context=main] [Extent=49:13:49:13]
-
-
+// CHECK: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 (Definition)
+// CHECK: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 (Definition)
+// CHECK: <invalid loc>:0:0: TypedefDecl=SEL:0:0 (Definition)
+// CHECK: <invalid loc>:0:0: TypeRef=SEL:0:0
+// CHECK: <invalid loc>:0:0: TypedefDecl=id:0:0 (Definition)
+// CHECK: <invalid loc>:0:0: TypedefDecl=Class:0:0 (Definition)
+// CHECK: <invalid loc>:87:16: StructDecl=__va_list_tag:87:16 (Definition)
+// CHECK: <invalid loc>:87:42: FieldDecl=gp_offset:87:42 (Definition)
+// CHECK: <invalid loc>:87:63: FieldDecl=fp_offset:87:63 (Definition)
+// CHECK: <invalid loc>:87:81: FieldDecl=overflow_arg_area:87:81 (Definition)
+// CHECK: <invalid loc>:87:107: FieldDecl=reg_save_area:87:107 (Definition)
+// CHECK: <invalid loc>:87:123: TypedefDecl=__va_list_tag:87:123 (Definition)
+// CHECK: <invalid loc>:87:9: TypeRef=struct __va_list_tag:87:16
+// CHECK: <invalid loc>:87:159: TypedefDecl=__builtin_va_list:87:159 (Definition)
+// CHECK: <invalid loc>:87:145: TypeRef=__va_list_tag:87:123
+// CHECK: <invalid loc>:87:177: UnexposedExpr=
+// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:12 [Extent=4:1:11:4]
+// CHECK: c-index-api-loadTU-test.m:8:1: ObjCInstanceMethodDecl=foo:8:1 [Extent=8:1:8:6]
+// CHECK: c-index-api-loadTU-test.m:9:1: ObjCClassMethodDecl=fooC:9:1 [Extent=9:1:9:7]
+// CHECK: c-index-api-loadTU-test.m:13:12: ObjCInterfaceDecl=Bar:13:12 [Extent=13:1:17:4]
+// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:4:12 [Extent=13:18:13:20]
+// CHECK: c-index-api-loadTU-test.m:19:12: ObjCCategoryDecl=FooCat:19:12 [Extent=19:1:22:4]
+// CHECK: c-index-api-loadTU-test.m:19:12: ObjCClassRef=Foo:4:12 [Extent=19:12:19:14]
+// CHECK: c-index-api-loadTU-test.m:20:1: ObjCInstanceMethodDecl=catMethodWithFloat::20:1 [Extent=20:1:20:40]
+// CHECK: c-index-api-loadTU-test.m:20:36: ParmDecl=fArg:20:36 (Definition) [Extent=20:29:20:39]
+// CHECK: c-index-api-loadTU-test.m:21:1: ObjCInstanceMethodDecl=floatMethod:21:1 [Extent=21:1:21:22]
+// CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolDecl=Proto:24:1 (Definition) [Extent=24:1:26:4]
+// CHECK: c-index-api-loadTU-test.m:25:1: ObjCInstanceMethodDecl=pMethod:25:1 [Extent=25:1:25:10]
+// CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolDecl=SubP:28:1 (Definition) [Extent=28:1:30:4]
+// CHECK: c-index-api-loadTU-test.m:28:17: ObjCProtocolRef=Proto:24:1 [Extent=28:17:28:21]
+// CHECK: c-index-api-loadTU-test.m:29:1: ObjCInstanceMethodDecl=spMethod:29:1 [Extent=29:1:29:11]
+// CHECK: c-index-api-loadTU-test.m:32:12: ObjCInterfaceDecl=Baz:32:12 [Extent=32:1:39:4]
+// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:13:12 [Extent=32:18:32:20]
+// CHECK: c-index-api-loadTU-test.m:32:23: ObjCProtocolRef=SubP:28:1 [Extent=32:23:32:26]
+// CHECK: c-index-api-loadTU-test.m:34:9: ObjCIvarDecl=_anIVar:34:9 (Definition) [Extent=34:9:34:15]
+// CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=bazMethod:37:1 [Extent=37:1:37:20]
+// CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 (Definition) [Extent=41:1:43:1]
+// CHECK: c-index-api-loadTU-test.m:42:3: EnumConstantDecl=someEnum:42:3 (Definition) [Extent=42:3:42:10]
+// CHECK: c-index-api-loadTU-test.m:45:5: FunctionDecl=main:45:5 (Definition) [Extent=45:5:54:1]
+// CHECK: c-index-api-loadTU-test.m:45:15: ParmDecl=argc:45:15 (Definition) [Extent=45:11:45:18]
+// CHECK: c-index-api-loadTU-test.m:45:34: ParmDecl=argv:45:34 (Definition) [Extent=45:27:45:37]
+// CHECK: c-index-api-loadTU-test.m:45:5: UnexposedStmt=main [Extent=45:42:54:1]
+// CHECK: c-index-api-loadTU-test.m:45:5: UnexposedStmt=main [Extent=46:2:46:11]
+// CHECK: c-index-api-loadTU-test.m:46:8: VarDecl=bee:46:8 (Definition) [Extent=46:2:46:10]
+// CHECK: c-index-api-loadTU-test.m:46:2: ObjCClassRef=Baz:32:12 [Extent=46:2:46:4]
+// CHECK: c-index-api-loadTU-test.m:46:8: UnexposedStmt=bee [Extent=47:2:47:18]
+// CHECK: c-index-api-loadTU-test.m:47:5: VarDecl=a:47:5 (Definition) [Extent=47:2:47:17]
+// CHECK: c-index-api-loadTU-test.m:47:2: TypeRef=id:0:0 [Extent=47:2:47:3]
+// CHECK: c-index-api-loadTU-test.m:47:9: ObjCMessageExpr=foo:8:1 [Extent=47:9:47:17]
+// CHECK: c-index-api-loadTU-test.m:47:10: DeclRefExpr=bee:46:8 [Extent=47:10:47:12]
+// CHECK: c-index-api-loadTU-test.m:47:5: UnexposedStmt=a [Extent=48:2:48:26]
+// CHECK: c-index-api-loadTU-test.m:48:12: VarDecl=c:48:12 (Definition) [Extent=48:2:48:25]
+// CHECK: c-index-api-loadTU-test.m:48:2: TypeRef=id:0:0 [Extent=48:2:48:3]
+// CHECK: c-index-api-loadTU-test.m:48:6: ObjCProtocolRef=SubP:28:1 [Extent=48:6:48:9]
+// CHECK: c-index-api-loadTU-test.m:48:16: UnexposedExpr=fooC:9:1 [Extent=48:16:48:25]
+// CHECK: c-index-api-loadTU-test.m:48:16: ObjCMessageExpr=fooC:9:1 [Extent=48:16:48:25]
+// CHECK: c-index-api-loadTU-test.m:48:12: UnexposedStmt=c [Extent=49:2:49:14]
+// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 (Definition) [Extent=49:2:49:13]
+// CHECK: c-index-api-loadTU-test.m:49:2: TypeRef=id:0:0 [Extent=49:2:49:3]
+// CHECK: c-index-api-loadTU-test.m:49:6: ObjCProtocolRef=Proto:24:1 [Extent=49:6:49:10]
+// CHECK: c-index-api-loadTU-test.m:50:2: UnexposedExpr= [Extent=50:2:50:6]
+// CHECK: c-index-api-loadTU-test.m:50:2: DeclRefExpr=d:49:13 [Extent=50:2:50:2]
+// CHECK: c-index-api-loadTU-test.m:50:6: UnexposedExpr=c:48:12 [Extent=50:6:50:6]
+// CHECK: c-index-api-loadTU-test.m:50:6: DeclRefExpr=c:48:12 [Extent=50:6:50:6]
+// CHECK: c-index-api-loadTU-test.m:51:2: ObjCMessageExpr=pMethod:25:1 [Extent=51:2:51:12]
+// CHECK: c-index-api-loadTU-test.m:51:3: DeclRefExpr=d:49:13 [Extent=51:3:51:3]
+// CHECK: c-index-api-loadTU-test.m:52:2: ObjCMessageExpr=catMethodWithFloat::20:1 [Extent=52:2:52:43]
+// CHECK: c-index-api-loadTU-test.m:52:3: DeclRefExpr=bee:46:8 [Extent=52:3:52:5]
+// CHECK: c-index-api-loadTU-test.m:52:26: ObjCMessageExpr=floatMethod:21:1 [Extent=52:26:52:42]
+// CHECK: c-index-api-loadTU-test.m:52:27: DeclRefExpr=bee:46:8 [Extent=52:27:52:29]
+// CHECK: c-index-api-loadTU-test.m:53:3: CallExpr=main:45:5 [Extent=53:3:53:36]
+// CHECK: c-index-api-loadTU-test.m:53:3: UnexposedExpr=main:45:5 [Extent=53:3:53:6]
+// CHECK: c-index-api-loadTU-test.m:53:3: DeclRefExpr=main:45:5 [Extent=53:3:53:6]
+// CHECK: c-index-api-loadTU-test.m:53:8: DeclRefExpr=someEnum:42:3 [Extent=53:8:53:15]
+// CHECK: c-index-api-loadTU-test.m:53:18: UnexposedExpr=bee:46:8 [Extent=53:18:53:35]
+// CHECK: c-index-api-loadTU-test.m:53:33: DeclRefExpr=bee:46:8 [Extent=53:33:53:35]
diff --git a/test/Index/c-index-getCursor-test.m b/test/Index/c-index-getCursor-test.m
index 03ab5a820835..8fb7ffc5ff94 100644
--- a/test/Index/c-index-getCursor-test.m
+++ b/test/Index/c-index-getCursor-test.m
@@ -53,108 +53,101 @@ int main (int argc, const char * argv[]) {
}
// CHECK: {start_line=1 start_col=1 end_line=2 end_col=62} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=3 start_col=1 end_line=6 end_col=1} ObjCInterfaceDecl=Foo:3:1
+// CHECK: {start_line=3 start_col=1 end_line=6 end_col=1} ObjCInterfaceDecl=Foo:3:12
// CHECK: {start_line=7 start_col=1 end_line=7 end_col=6} ObjCInstanceMethodDecl=foo:7:1
-// CHECK: {start_line=7 start_col=7 end_line=7 end_col=7} ObjCInterfaceDecl=Foo:3:1
+// CHECK: {start_line=7 start_col=7 end_line=7 end_col=7} ObjCInterfaceDecl=Foo:3:12
// CHECK: {start_line=8 start_col=1 end_line=8 end_col=7} ObjCClassMethodDecl=fooC:8:1
-// CHECK: {start_line=8 start_col=8 end_line=10 end_col=4} ObjCInterfaceDecl=Foo:3:1
+// CHECK: {start_line=8 start_col=8 end_line=10 end_col=4} ObjCInterfaceDecl=Foo:3:12
// CHECK: {start_line=10 start_col=5 end_line=11 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=12 start_col=1 end_line=16 end_col=4} ObjCInterfaceDecl=Bar:12:1
+// CHECK: {start_line=12 start_col=1 end_line=12 end_col=17} ObjCInterfaceDecl=Bar:12:12
+// CHECK: {start_line=12 start_col=18 end_line=12 end_col=20} ObjCSuperClassRef=Foo:3:12
+// CHECK: {start_line=12 start_col=21 end_line=16 end_col=4} ObjCInterfaceDecl=Bar:12:12
// CHECK: {start_line=16 start_col=5 end_line=17 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=18 start_col=1 end_line=18 end_col=24} ObjCCategoryDecl=FooCat:18:1
+// CHECK: {start_line=18 start_col=1 end_line=18 end_col=11} ObjCCategoryDecl=FooCat:18:12
+// CHECK: {start_line=18 start_col=12 end_line=18 end_col=14} ObjCClassRef=Foo:3:12
+// CHECK: {start_line=18 start_col=15 end_line=18 end_col=24} ObjCCategoryDecl=FooCat:18:12
// CHECK: {start_line=19 start_col=1 end_line=19 end_col=28} ObjCInstanceMethodDecl=catMethodWithFloat::19:1
-// CHECK: {start_line=19 start_col=29 end_line=19 end_col=33} ParmDecl=fArg:19:36
-// CHECK: {start_line=19 start_col=34 end_line=19 end_col=35} ObjCInstanceMethodDecl=catMethodWithFloat::19:1
-// CHECK: {start_line=19 start_col=36 end_line=19 end_col=39} ParmDecl=fArg:19:36
+// CHECK: {start_line=19 start_col=29 end_line=19 end_col=39} ParmDecl=fArg:19:36 (Definition)
// CHECK: {start_line=19 start_col=40 end_line=19 end_col=40} ObjCInstanceMethodDecl=catMethodWithFloat::19:1
-// CHECK: {start_line=19 start_col=41 end_line=19 end_col=41} ObjCCategoryDecl=FooCat:18:1
+// CHECK: {start_line=19 start_col=41 end_line=19 end_col=41} ObjCCategoryDecl=FooCat:18:12
// CHECK: {start_line=20 start_col=1 end_line=20 end_col=22} ObjCInstanceMethodDecl=floatMethod:20:1
-// CHECK: {start_line=20 start_col=23 end_line=21 end_col=4} ObjCCategoryDecl=FooCat:18:1
+// CHECK: {start_line=20 start_col=23 end_line=21 end_col=4} ObjCCategoryDecl=FooCat:18:12
// CHECK: {start_line=21 start_col=5 end_line=22 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=23 start_col=1 end_line=23 end_col=16} ObjCProtocolDecl=Proto:23:1
+// CHECK: {start_line=23 start_col=1 end_line=23 end_col=16} ObjCProtocolDecl=Proto:23:1 (Definition)
// CHECK: {start_line=24 start_col=1 end_line=24 end_col=10} ObjCInstanceMethodDecl=pMethod:24:1
-// CHECK: {start_line=24 start_col=11 end_line=25 end_col=4} ObjCProtocolDecl=Proto:23:1
+// CHECK: {start_line=24 start_col=11 end_line=25 end_col=4} ObjCProtocolDecl=Proto:23:1 (Definition)
// CHECK: {start_line=25 start_col=5 end_line=26 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=27 start_col=1 end_line=27 end_col=23} ObjCProtocolDecl=SubP:27:1
+// CHECK: {start_line=27 start_col=1 end_line=27 end_col=16} ObjCProtocolDecl=SubP:27:1 (Definition)
+// CHECK: {start_line=27 start_col=17 end_line=27 end_col=21} ObjCProtocolRef=Proto:23:1
+// CHECK: {start_line=27 start_col=22 end_line=27 end_col=23} ObjCProtocolDecl=SubP:27:1 (Definition)
// CHECK: {start_line=28 start_col=1 end_line=28 end_col=11} ObjCInstanceMethodDecl=spMethod:28:1
-// CHECK: {start_line=28 start_col=12 end_line=29 end_col=4} ObjCProtocolDecl=SubP:27:1
+// CHECK: {start_line=28 start_col=12 end_line=29 end_col=4} ObjCProtocolDecl=SubP:27:1 (Definition)
// CHECK: {start_line=29 start_col=5 end_line=30 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=31 start_col=1 end_line=33 end_col=4} ObjCInterfaceDecl=Baz:31:1
-// CHECK: {start_line=33 start_col=5 end_line=33 end_col=7} Invalid Cursor => NotImplemented
-// CHECK: {start_line=33 start_col=8 end_line=33 end_col=8} ObjCInterfaceDecl=Baz:31:1
-// CHECK: {start_line=33 start_col=9 end_line=33 end_col=15} Invalid Cursor => NotImplemented
-// CHECK: {start_line=33 start_col=16 end_line=35 end_col=1} ObjCInterfaceDecl=Baz:31:1
+// CHECK: {start_line=31 start_col=1 end_line=31 end_col=17} ObjCInterfaceDecl=Baz:31:12
+// CHECK: {start_line=31 start_col=18 end_line=31 end_col=20} ObjCSuperClassRef=Bar:12:12
+// CHECK: {start_line=31 start_col=21 end_line=31 end_col=22} ObjCInterfaceDecl=Baz:31:12
+// CHECK: {start_line=31 start_col=23 end_line=31 end_col=26} ObjCProtocolRef=SubP:27:1
+// CHECK: {start_line=31 start_col=27 end_line=33 end_col=8} ObjCInterfaceDecl=Baz:31:12
+// CHECK: {start_line=33 start_col=9 end_line=33 end_col=15} ObjCIvarDecl=_anIVar:33:9 (Definition)
+// CHECK: {start_line=33 start_col=16 end_line=35 end_col=1} ObjCInterfaceDecl=Baz:31:12
// CHECK: {start_line=36 start_col=1 end_line=36 end_col=20} ObjCInstanceMethodDecl=bazMethod:36:1
-// CHECK: {start_line=36 start_col=21 end_line=38 end_col=4} ObjCInterfaceDecl=Baz:31:1
+// CHECK: {start_line=36 start_col=21 end_line=38 end_col=4} ObjCInterfaceDecl=Baz:31:12
// CHECK: {start_line=38 start_col=5 end_line=39 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=40 start_col=1 end_line=41 end_col=2} EnumDecl=:40:1
-// CHECK: {start_line=41 start_col=3 end_line=41 end_col=10} EnumConstantDecl=someEnum:41:3
-// CHECK: {start_line=41 start_col=11 end_line=42 end_col=1} EnumDecl=:40:1
-// CHECK: {start_line=42 start_col=2 end_line=43 end_col=1} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=44 start_col=1 end_line=44 end_col=3} FunctionDecl=main:44:5
-// CHECK: {start_line=44 start_col=4 end_line=44 end_col=4} Invalid Cursor => NoDeclFound
-// CHECK: {start_line=44 start_col=5 end_line=44 end_col=10} FunctionDecl=main:44:5
-// CHECK: {start_line=44 start_col=11 end_line=44 end_col=13} ParmDecl=argc:44:15
-// CHECK: {start_line=44 start_col=14 end_line=44 end_col=14} FunctionDecl=main:44:5
-// CHECK: {start_line=44 start_col=15 end_line=44 end_col=18} ParmDecl=argc:44:15
-// CHECK: {start_line=44 start_col=19 end_line=44 end_col=26} FunctionDecl=main:44:5
-// CHECK: {start_line=44 start_col=27 end_line=44 end_col=30} ParmDecl=argv:44:34
-// CHECK: {start_line=44 start_col=31 end_line=44 end_col=31} FunctionDecl=main:44:5
-// CHECK: {start_line=44 start_col=32 end_line=44 end_col=32} ParmDecl=argv:44:34
-// CHECK: {start_line=44 start_col=33 end_line=44 end_col=33} FunctionDecl=main:44:5
-// CHECK: {start_line=44 start_col=34 end_line=44 end_col=39} ParmDecl=argv:44:34
-// CHECK: {start_line=44 start_col=40 end_line=45 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=45 start_col=2 end_line=45 end_col=4} ObjCClassRef=Baz:45:8
-// CHECK: {start_line=45 start_col=5 end_line=45 end_col=5} FunctionDecl=main:44:5
-// CHECK: {start_line=45 start_col=6 end_line=45 end_col=6} VarDecl=bee:45:8
-// CHECK: {start_line=45 start_col=7 end_line=45 end_col=7} FunctionDecl=main:44:5
-// CHECK: {start_line=45 start_col=8 end_line=45 end_col=10} VarDecl=bee:45:8
-// CHECK: {start_line=45 start_col=11 end_line=46 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=46 start_col=2 end_line=46 end_col=3} TypedefDecl=id:0:0
-// CHECK: {start_line=46 start_col=4 end_line=46 end_col=4} FunctionDecl=main:44:5
-// CHECK: {start_line=46 start_col=5 end_line=46 end_col=8} VarDecl=a:46:5
-// CHECK: {start_line=46 start_col=9 end_line=46 end_col=9} ObjCSelectorRef=foo:7:1
-// CHECK: {start_line=46 start_col=10 end_line=46 end_col=12} VarRef=bee:45:8
-// CHECK: {start_line=46 start_col=13 end_line=46 end_col=17} ObjCSelectorRef=foo:7:1
-// CHECK: {start_line=46 start_col=18 end_line=47 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=47 start_col=2 end_line=47 end_col=3} TypedefDecl=id:0:0
-// CHECK: {start_line=47 start_col=4 end_line=47 end_col=4} FunctionDecl=main:44:5
-// CHECK: {start_line=47 start_col=5 end_line=47 end_col=5} VarDecl=c:47:12
-// CHECK: {start_line=47 start_col=6 end_line=47 end_col=9} ObjCProtocolRef=SubP:47:12
-// CHECK: {start_line=47 start_col=10 end_line=47 end_col=10} VarDecl=c:47:12
-// CHECK: {start_line=47 start_col=11 end_line=47 end_col=11} FunctionDecl=main:44:5
-// CHECK: {start_line=47 start_col=12 end_line=47 end_col=15} VarDecl=c:47:12
-// CHECK: {start_line=47 start_col=16 end_line=47 end_col=25} ObjCSelectorRef=fooC:8:1
-// CHECK: {start_line=47 start_col=26 end_line=48 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=48 start_col=2 end_line=48 end_col=3} TypedefDecl=id:0:0
-// CHECK: {start_line=48 start_col=4 end_line=48 end_col=4} FunctionDecl=main:44:5
-// CHECK: {start_line=48 start_col=5 end_line=48 end_col=5} VarDecl=d:48:13
-// CHECK: {start_line=48 start_col=6 end_line=48 end_col=10} ObjCProtocolRef=Proto:48:13
-// CHECK: {start_line=48 start_col=11 end_line=48 end_col=11} VarDecl=d:48:13
-// CHECK: {start_line=48 start_col=12 end_line=48 end_col=12} FunctionDecl=main:44:5
-// CHECK: {start_line=48 start_col=13 end_line=48 end_col=13} VarDecl=d:48:13
-// CHECK: {start_line=48 start_col=14 end_line=49 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=49 start_col=2 end_line=49 end_col=2} VarRef=d:48:13
-// CHECK: {start_line=49 start_col=3 end_line=49 end_col=5} FunctionDecl=main:44:5
-// CHECK: {start_line=49 start_col=6 end_line=49 end_col=6} VarRef=c:47:12
-// CHECK: {start_line=49 start_col=7 end_line=50 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=50 start_col=2 end_line=50 end_col=2} ObjCSelectorRef=pMethod:24:1
-// CHECK: {start_line=50 start_col=3 end_line=50 end_col=3} VarRef=d:48:13
-// CHECK: {start_line=50 start_col=4 end_line=50 end_col=12} ObjCSelectorRef=pMethod:24:1
-// CHECK: {start_line=50 start_col=13 end_line=51 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=51 start_col=2 end_line=51 end_col=2} ObjCSelectorRef=catMethodWithFloat::19:1
-// CHECK: {start_line=51 start_col=3 end_line=51 end_col=5} VarRef=bee:45:8
-// CHECK: {start_line=51 start_col=6 end_line=51 end_col=25} ObjCSelectorRef=catMethodWithFloat::19:1
-// CHECK: {start_line=51 start_col=26 end_line=51 end_col=26} ObjCSelectorRef=floatMethod:20:1
-// CHECK: {start_line=51 start_col=27 end_line=51 end_col=29} VarRef=bee:45:8
-// CHECK: {start_line=51 start_col=30 end_line=51 end_col=42} ObjCSelectorRef=floatMethod:20:1
-// CHECK: {start_line=51 start_col=43 end_line=51 end_col=43} ObjCSelectorRef=catMethodWithFloat::19:1
-// CHECK: {start_line=51 start_col=44 end_line=52 end_col=2} FunctionDecl=main:44:5
-// CHECK: {start_line=52 start_col=3 end_line=52 end_col=6} FunctionRef=main:44:5
-// CHECK: {start_line=52 start_col=7 end_line=52 end_col=7} FunctionDecl=main:44:5
-// CHECK: {start_line=52 start_col=8 end_line=52 end_col=15} EnumConstantRef=someEnum:41:3
-// CHECK: {start_line=52 start_col=16 end_line=52 end_col=32} FunctionDecl=main:44:5
-// CHECK: {start_line=52 start_col=33 end_line=52 end_col=35} VarRef=bee:45:8
-// CHECK: {start_line=52 start_col=36 end_line=53 end_col=1} FunctionDecl=main:44:5
-// CHECK: {start_line=53 start_col=2 end_line=160 end_col=1} Invalid Cursor => NoDeclFound
-
+// CHECK: {start_line=40 start_col=1 end_line=41 end_col=2} EnumDecl=:40:1 (Definition)
+// CHECK: {start_line=41 start_col=3 end_line=41 end_col=10} EnumConstantDecl=someEnum:41:3 (Definition)
+// CHECK: {start_line=41 start_col=11 end_line=42 end_col=1} EnumDecl=:40:1 (Definition)
+// CHECK: {start_line=42 start_col=2 end_line=44 end_col=4} Invalid Cursor => NoDeclFound
+// CHECK: {start_line=44 start_col=5 end_line=44 end_col=10} FunctionDecl=main:44:5 (Definition)
+// CHECK: {start_line=44 start_col=11 end_line=44 end_col=18} ParmDecl=argc:44:15 (Definition)
+// CHECK: {start_line=44 start_col=19 end_line=44 end_col=26} FunctionDecl=main:44:5 (Definition)
+// CHECK: {start_line=44 start_col=27 end_line=44 end_col=37} ParmDecl=argv:44:34 (Definition)
+// CHECK: {start_line=44 start_col=38 end_line=44 end_col=41} FunctionDecl=main:44:5 (Definition)
+// CHECK: {start_line=44 start_col=42 end_line=45 end_col=1} UnexposedStmt=main
+// CHECK: {start_line=45 start_col=2 end_line=45 end_col=4} ObjCClassRef=Baz:31:12
+// CHECK: {start_line=45 start_col=5 end_line=45 end_col=10} VarDecl=bee:45:8 (Definition)
+// CHECK: {start_line=45 start_col=11 end_line=45 end_col=11} UnexposedStmt=main
+// CHECK: {start_line=45 start_col=12 end_line=46 end_col=1} UnexposedStmt=main
+// CHECK: {start_line=46 start_col=2 end_line=46 end_col=3} TypeRef=id:0:0
+// CHECK: {start_line=46 start_col=4 end_line=46 end_col=8} VarDecl=a:46:5 (Definition)
+// CHECK: {start_line=46 start_col=9 end_line=46 end_col=9} ObjCMessageExpr=foo:7:1
+// CHECK: {start_line=46 start_col=10 end_line=46 end_col=12} DeclRefExpr=bee:45:8
+// CHECK: {start_line=46 start_col=13 end_line=46 end_col=17} ObjCMessageExpr=foo:7:1
+// CHECK: {start_line=46 start_col=18 end_line=46 end_col=18} UnexposedStmt=main
+// CHECK: {start_line=46 start_col=19 end_line=47 end_col=1} UnexposedStmt=main
+// CHECK: {start_line=47 start_col=2 end_line=47 end_col=3} TypeRef=id:0:0
+// CHECK: {start_line=47 start_col=4 end_line=47 end_col=5} VarDecl=c:47:12 (Definition)
+// CHECK: {start_line=47 start_col=6 end_line=47 end_col=9} ObjCProtocolRef=SubP:27:1
+// CHECK: {start_line=47 start_col=10 end_line=47 end_col=15} VarDecl=c:47:12 (Definition)
+// CHECK: {start_line=47 start_col=16 end_line=47 end_col=25} ObjCMessageExpr=fooC:8:1
+// CHECK: {start_line=47 start_col=26 end_line=47 end_col=26} UnexposedStmt=main
+// CHECK: {start_line=47 start_col=27 end_line=48 end_col=1} UnexposedStmt=main
+// CHECK: {start_line=48 start_col=2 end_line=48 end_col=3} TypeRef=id:0:0
+// CHECK: {start_line=48 start_col=4 end_line=48 end_col=5} VarDecl=d:48:13 (Definition)
+// CHECK: {start_line=48 start_col=6 end_line=48 end_col=10} ObjCProtocolRef=Proto:23:1
+// CHECK: {start_line=48 start_col=11 end_line=48 end_col=13} VarDecl=d:48:13 (Definition)
+// CHECK: {start_line=48 start_col=14 end_line=48 end_col=14} UnexposedStmt=main
+// CHECK: {start_line=48 start_col=15 end_line=49 end_col=1} UnexposedStmt=main
+// CHECK: {start_line=49 start_col=2 end_line=49 end_col=2} DeclRefExpr=d:48:13
+// CHECK: {start_line=49 start_col=3 end_line=49 end_col=5} UnexposedExpr=
+// CHECK: {start_line=49 start_col=6 end_line=49 end_col=6} DeclRefExpr=c:47:12
+// CHECK: {start_line=49 start_col=7 end_line=50 end_col=1} UnexposedStmt=main
+// CHECK: {start_line=50 start_col=2 end_line=50 end_col=2} ObjCMessageExpr=pMethod:24:1
+// CHECK: {start_line=50 start_col=3 end_line=50 end_col=3} DeclRefExpr=d:48:13
+// CHECK: {start_line=50 start_col=4 end_line=50 end_col=12} ObjCMessageExpr=pMethod:24:1
+// CHECK: {start_line=50 start_col=13 end_line=51 end_col=1} UnexposedStmt=main
+// CHECK: {start_line=51 start_col=2 end_line=51 end_col=2} ObjCMessageExpr=catMethodWithFloat::19:1
+// CHECK: {start_line=51 start_col=3 end_line=51 end_col=5} DeclRefExpr=bee:45:8
+// CHECK: {start_line=51 start_col=6 end_line=51 end_col=25} ObjCMessageExpr=catMethodWithFloat::19:1
+// CHECK: {start_line=51 start_col=26 end_line=51 end_col=26} ObjCMessageExpr=floatMethod:20:1
+// CHECK: {start_line=51 start_col=27 end_line=51 end_col=29} DeclRefExpr=bee:45:8
+// CHECK: {start_line=51 start_col=30 end_line=51 end_col=42} ObjCMessageExpr=floatMethod:20:1
+// CHECK: {start_line=51 start_col=43 end_line=51 end_col=43} ObjCMessageExpr=catMethodWithFloat::19:1
+// CHECK: {start_line=51 start_col=44 end_line=52 end_col=2} UnexposedStmt=main
+// CHECK: {start_line=52 start_col=3 end_line=52 end_col=6} DeclRefExpr=main:44:5
+// CHECK: {start_line=52 start_col=7 end_line=52 end_col=7} CallExpr=main:44:5
+// CHECK: {start_line=52 start_col=8 end_line=52 end_col=15} DeclRefExpr=someEnum:41:3
+// CHECK: {start_line=52 start_col=16 end_line=52 end_col=17} CallExpr=main:44:5
+// CHECK: {start_line=52 start_col=18 end_line=52 end_col=32} UnexposedExpr=bee:45:8
+// CHECK: {start_line=52 start_col=33 end_line=52 end_col=35} DeclRefExpr=bee:45:8
+// CHECK: {start_line=52 start_col=36 end_line=52 end_col=36} CallExpr=main:44:5
+// CHECK: {start_line=52 start_col=37 end_line=53 end_col=1} UnexposedStmt=main
diff --git a/test/Index/cindex-from-source.m b/test/Index/cindex-from-source.m
index e775bb71e11e..8f79304cb68b 100644
--- a/test/Index/cindex-from-source.m
+++ b/test/Index/cindex-from-source.m
@@ -2,8 +2,8 @@
// RUN: %clang -x objective-c-header %t.pfx.h -o %t.pfx.h.gch
// RUN: c-index-test -test-load-source local %s -include %t.pfx.h > %t
// RUN: FileCheck %s < %t
-// CHECK: cindex-from-source.m:{{.*}}:{{.*}}: StructDecl=s0:{{.*}}:{{.*}} [Context=cindex-from-source.m]
-// CHECK: cindex-from-source.m:{{.*}}:{{.*}}: VarDecl=g0:{{.*}}:{{.*}} [Context=cindex-from-source.m]
-
+// CHECK: cindex-from-source.m:{{.*}}:{{.*}}: StructDecl=s0:{{.*}}:{{.*}}
+// CHECK: cindex-from-source.m:{{.*}}:{{.*}}: VarDecl=g0:{{.*}}:{{.*}}
+// CHECK: cindex-from-source.m:9:1: TypeRef=t0:1:13 [Extent=9:1:9:2]
struct s0 {};
t0 g0;
diff --git a/test/Index/comments.c b/test/Index/comments.c
deleted file mode 100644
index 034317779c6e..000000000000
--- a/test/Index/comments.c
+++ /dev/null
@@ -1,34 +0,0 @@
-// Run lines are sensitive to line numbers and come below the code.
-
-//! It all starts here.
-/*! It's a little odd to continue line this,
- *
- * but we need more multi-line comments. */
-/// This comment comes before my other comments
-/** This is a block comment that is associated with the function f. It
- * runs for three lines.
- */
-void f(int, int);
-
-// NOT IN THE COMMENT
-/// This is a BCPL comment that is associated with the function g.
-/// It has only two lines.
-/** But there are other blocks that are part of the comment, too. */
-void g(int);
-
-void h(int); ///< This is a member comment.
-
-
-// RUN: %clang_cc1 -emit-pch -o %t.ast %s
-
-// RUN: index-test %t.ast -point-at %s:11:6 > %t
-// RUN: grep "starts here" %t
-// RUN: grep "block comment" %t
-
-// RUN: index-test %t.ast -point-at %s:17:6 > %t
-// RUN: grep "BCPL" %t
-// RUN: grep "But" %t
-
-// RUN: index-test %t.ast -point-at %s:19:6 > %t
-// RUN: grep "NOT" %t | count 0
-// RUN: grep "member" %t
diff --git a/test/Index/find-decls.c b/test/Index/find-decls.c
deleted file mode 100644
index f1999b2151b4..000000000000
--- a/test/Index/find-decls.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: %clang_cc1 -fblocks -emit-pch %S/Inputs/t1.c -o %t1.ast
-// RUN: %clang_cc1 -fblocks -emit-pch %S/Inputs/t2.c -o %t2.ast
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:8:7 -print-decls > %t
-// RUN: cat %t | count 3
-// RUN: grep 'foo.h:4:6,' %t | count 2
-// RUN: grep 't2.c:5:6,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:5:47 -print-decls > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:5:12,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:6:20 -print-decls > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:3:19,' %t
-
-// field test
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:21:6 -print-decls > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:12:7,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:22:21 -print-decls > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:16:7,' %t
diff --git a/test/Index/find-defs.c b/test/Index/find-defs.c
deleted file mode 100644
index 51292704a1b6..000000000000
--- a/test/Index/find-defs.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %clang_cc1 -fblocks -emit-pch %S/Inputs/t1.c -o %t1.ast
-// RUN: %clang_cc1 -fblocks -emit-pch %S/Inputs/t2.c -o %t2.ast
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/foo.h:1:14 -print-defs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't2.c:3:5,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/foo.h:3:9 -print-defs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:3:6,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/foo.h:4:9 -print-defs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't2.c:5:6,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:8:7 -print-defs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't2.c:5:6,' %t
diff --git a/test/Index/find-refs.c b/test/Index/find-refs.c
deleted file mode 100644
index 1f29a77017de..000000000000
--- a/test/Index/find-refs.c
+++ /dev/null
@@ -1,47 +0,0 @@
-// RUN: %clang_cc1 -fblocks -emit-pch %S/Inputs/t1.c -o %t1.ast
-// RUN: %clang_cc1 -fblocks -emit-pch %S/Inputs/t2.c -o %t2.ast
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/foo.h:1:14 -print-refs > %t
-// RUN: cat %t | count 4
-// RUN: grep 't1.c:4:19,' %t
-// RUN: grep 't1.c:28:40,' %t
-// RUN: grep 't2.c:6:3,' %t
-// RUN: grep 't2.c:7:12,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/foo.h:3:9 -print-refs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't2.c:7:3,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/foo.h:4:9 -print-refs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:8:3,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:3:22 -print-refs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:6:17,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:4:11 -print-refs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:6:5,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:5:30 -print-refs > %t
-// RUN: cat %t | count 3
-// RUN: grep 't1.c:5:27,' %t
-// RUN: grep 't1.c:5:44,' %t
-// RUN: grep 't1.c:6:26,' %t
-
-// field test
-
-// FIXME: References point at the start of MemberExpr, make them point at the field instead.
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:12:7 -print-refs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:21:3,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/t1.c:16:7 -print-refs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.c:22:3,' %t
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/Inputs/foo.h:7:11 -print-refs > %t
-// RUN: cat %t | count 2
-// RUN: grep 't1.c:25:3,' %t
-// RUN: grep 't2.c:10:3,' %t
diff --git a/test/Index/load-exprs.c b/test/Index/load-exprs.c
new file mode 100644
index 000000000000..a360efd755a4
--- /dev/null
+++ b/test/Index/load-exprs.c
@@ -0,0 +1,13 @@
+typedef int T;
+struct X { int a, b; };
+void f(void *ptr) {
+ T* t_ptr = (T *)ptr;
+ (void)sizeof(T);
+ struct X x = (struct X){1, 2};
+}
+
+// RUN: c-index-test -test-load-source all %s | FileCheck %s
+
+// CHECK: load-exprs.c:4:15: TypeRef=T:1:13 [Extent=4:15:4:15]
+// CHECK: load-exprs.c:5:16: TypeRef=T:1:13 [Extent=5:16:5:16]
+// FIXME: the source location for "struct X" points at "struct", not "X"
diff --git a/test/Index/multiple-redecls.c b/test/Index/multiple-redecls.c
deleted file mode 100644
index faea88fc6b77..000000000000
--- a/test/Index/multiple-redecls.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang_cc1 -emit-pch %s -o %t.ast
-// RUN: index-test %t.ast -point-at %s:8:4 -print-decls | count 2
-// RUN: index-test %t.ast -point-at %s:8:4 -print-defs | count 1
-
-static void foo(int x);
-
-static void bar(void) {
- foo(10);
-}
-
-void foo(int x) {
-}
diff --git a/test/Index/objc-decls.m b/test/Index/objc-decls.m
deleted file mode 100644
index 4fcd830212bb..000000000000
--- a/test/Index/objc-decls.m
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %clang_cc1 -emit-pch %S/Inputs/t1.m -o %t1.m.ast
-// RUN: %clang_cc1 -emit-pch %S/Inputs/t2.m -o %t2.m.ast
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/t1.m:12:12 -print-decls > %t
-// RUN: cat %t | count 2
-// RUN: grep 'objc.h:2:9,' %t | count 2
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/objc.h:5:13 -print-decls > %t
-// RUN: cat %t | count 3
-// RUN: grep 'objc.h:5:1,' %t | count 2
-// RUN: grep 't1.m:15:1,' %t | count 1
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/objc.h:10:13 -print-decls > %t
-// RUN: cat %t | count 3
-// RUN: grep 'objc.h:10:1,' %t | count 2
-// RUN: grep 't2.m:11:1,' %t | count 1
diff --git a/test/Index/objc-message.m b/test/Index/objc-message.m
deleted file mode 100644
index 151565b9bba2..000000000000
--- a/test/Index/objc-message.m
+++ /dev/null
@@ -1,38 +0,0 @@
-// RUN: %clang_cc1 -emit-pch %S/Inputs/t1.m -o %t1.m.ast
-// RUN: %clang_cc1 -emit-pch %S/Inputs/t2.m -o %t2.m.ast
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/objc.h:5:13 -print-refs > %t
-// RUN: cat %t | count 1
-// RUN: grep 't1.m:6:3,' %t
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/objc.h:6:13 -print-refs > %t
-// RUN: cat %t | count 2
-// RUN: grep 't1.m:7:3,' %t
-// RUN: grep 't2.m:7:3,' %t
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/objc.h:10:13 -print-refs > %t
-// RUN: cat %t | count 2
-// RUN: grep 't1.m:6:3,' %t
-// RUN: grep 't2.m:6:3,' %t
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/t1.m:6:15 -print-decls > %t
-// RUN: cat %t | count 6
-// RUN: grep 'objc.h:5:1,' %t | count 2
-// RUN: grep 'objc.h:10:1,' %t | count 2
-// RUN: grep 't1.m:15:1,' %t
-// RUN: grep 't2.m:11:1,' %t
-
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/Inputs/t1.m:7:15 -print-decls > %t
-// RUN: cat %t | count 3
-// RUN: grep 'objc.h:6:1,' %t | count 2
-// RUN: grep 't1.m:18:1,' %t
-
-// RUN: index-test %t2.m.ast %t1.m.ast -point-at %S/Inputs/t2.m:6:15 -print-decls > %t
-// RUN: cat %t | count 3
-// RUN: grep 'objc.h:10:1,' %t | count 2
-// RUN: grep 't2.m:11:1,' %t
-
-// RUN: index-test %t2.m.ast %t1.m.ast -point-at %S/Inputs/t2.m:7:15 -print-decls > %t
-// RUN: cat %t | count 3
-// RUN: grep 'objc.h:6:1,' %t | count 2
-// RUN: grep 't1.m:18:1,' %t
diff --git a/test/Index/remap-cursor-at.c b/test/Index/remap-cursor-at.c
new file mode 100644
index 000000000000..f7bcf79b759f
--- /dev/null
+++ b/test/Index/remap-cursor-at.c
@@ -0,0 +1,5 @@
+// RUN: c-index-test -cursor-at=%s:1:15 -cursor-at=%s:2:21 -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck %s
+// RUN: CINDEXTEST_USE_EXTERNAL_AST_GENERATION=1 c-index-test -cursor-at=%s:1:15 -cursor-at=%s:2:21 -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck %s
+
+// CHECK: ParmDecl=parm1:1:13 (Definition)
+// CHECK: DeclRefExpr=parm2:1:26
diff --git a/test/Index/remap-load.c b/test/Index/remap-load.c
new file mode 100644
index 000000000000..84e45bcda40d
--- /dev/null
+++ b/test/Index/remap-load.c
@@ -0,0 +1,13 @@
+// RUN: c-index-test -test-load-source all -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck -check-prefix=CHECK %s
+// RUN: CINDEXTEST_USE_EXTERNAL_AST_GENERATION=1 c-index-test -test-load-source all -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck -check-prefix=CHECK %s
+
+// CHECK: remap-load.c:1:5: FunctionDecl=foo:1:5 (Definition) [Extent=1:5:3:1]
+// CHECK: remap-load.c:1:13: ParmDecl=parm1:1:13 (Definition) [Extent=1:9:1:17]
+// CHECK: remap-load.c:1:26: ParmDecl=parm2:1:26 (Definition) [Extent=1:20:1:30]
+// CHECK: remap-load.c:1:5: UnexposedStmt=foo [Extent=1:33:3:1]
+// CHECK: remap-load.c:1:5: UnexposedStmt=foo [Extent=2:3:2:22]
+// CHECK: remap-load.c:2:10: UnexposedExpr= [Extent=2:10:2:22]
+// CHECK: remap-load.c:2:10: UnexposedExpr= [Extent=2:10:2:22]
+// CHECK: remap-load.c:2:10: UnexposedExpr=parm1:1:13 [Extent=2:10:2:14]
+// CHECK: remap-load.c:2:10: DeclRefExpr=parm1:1:13 [Extent=2:10:2:14]
+// CHECK: remap-load.c:2:18: DeclRefExpr=parm2:1:26 [Extent=2:18:2:22]
diff --git a/test/Index/resolve-loc.c b/test/Index/resolve-loc.c
deleted file mode 100644
index 68504ee0d2bc..000000000000
--- a/test/Index/resolve-loc.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// Run lines are sensitive to line numbers and come below the code.
-
-int top_var;
-
-void top_func_decl(int param1);
-
-void top_func_def(int param2) {
- int local_var1;
- for (int for_var = 100; for_var < 500; ++for_var) {
- int local_var2 = for_var + 1;
- }
-}
-
-struct S {
- int field_var;
-};
-
-
-// RUN: %clang_cc1 -emit-pch %s -o %t.ast
-// RUN: index-test %t.ast -point-at %s:3:8 | grep top_var
-// RUN: index-test %t.ast -point-at %s:5:15 | grep top_func_decl
-// RUN: index-test %t.ast -point-at %s:5:25 | grep param1
-// RUN: index-test %t.ast -point-at %s:7:17 | grep top_func_def
-// RUN: index-test %t.ast -point-at %s:7:23 | grep param2
-// RUN: index-test %t.ast -point-at %s:8:10 | grep local_var1
-// RUN: index-test %t.ast -point-at %s:9:15 | grep for_var
-
-// RUN: index-test %t.ast -point-at %s:9:43 > %t
-// RUN: grep '++for_var' %t
-
-// RUN: index-test %t.ast -point-at %s:10:9 | grep local_var2
-
-// RUN: index-test %t.ast -point-at %s:10:30 > %t
-// RUN: grep 'for_var + 1' %t
-
-// fields test.
-// RUN: index-test %t.ast -point-at %s:15:10 | grep field_var
diff --git a/test/Lexer/constants-ms.c b/test/Lexer/constants-ms.c
index 5b3f82611977..97e660080d45 100644
--- a/test/Lexer/constants-ms.c
+++ b/test/Lexer/constants-ms.c
@@ -7,6 +7,19 @@ __int64 x5 = 0x42i64;
__int64 x4 = 70000000i128;
__int64 y = 0x42i64u; // expected-error {{invalid suffix}}
-__int64 w = 0x43ui64; // expected-error {{invalid suffix}}
+__int64 w = 0x43ui64;
__int64 z = 9Li64; // expected-error {{invalid suffix}}
__int64 q = 10lli64; // expected-error {{invalid suffix}}
+
+// radar 7562363
+#define ULLONG_MAX 0xffffffffffffffffui64
+#define UINT 0xffffffffui32
+#define USHORT 0xffffui16
+#define UCHAR 0xffui8
+
+void a() {
+ unsigned long long m = ULLONG_MAX;
+ unsigned int n = UINT;
+ unsigned short s = USHORT;
+ unsigned char c = UCHAR;
+}
diff --git a/test/Misc/tabstop.c b/test/Misc/tabstop.c
index 3fabda76eb8c..66685c62d15a 100644
--- a/test/Misc/tabstop.c
+++ b/test/Misc/tabstop.c
@@ -28,3 +28,23 @@ void* d = 1;
//CHECK-5: {{^ void\* b = 1;}}
//CHECK-5: {{^ void\* c = 1;}}
//CHECK-5: {{^void\* d = 1;}}
+
+// Test code modification hints
+
+void f(void)
+{
+ if (0 & 1 == 1)
+ {}
+}
+
+// CHECK-3: {{^ }}if (0 & 1 == 1)
+// CHECK-3: {{^ }} ( )
+// CHECK-3: {{^ }} ( )
+
+// CHECK-4: {{^ }}if (0 & 1 == 1)
+// CHECK-4: {{^ }} ( )
+// CHECK-4: {{^ }} ( )
+
+// CHECK-5: {{^ }}if (0 & 1 == 1)
+// CHECK-5: {{^ }} ( )
+// CHECK-5: {{^ }} ( )
diff --git a/test/PCH/cxx_exprs.cpp b/test/PCH/cxx_exprs.cpp
new file mode 100644
index 000000000000..51269d57b147
--- /dev/null
+++ b/test/PCH/cxx_exprs.cpp
@@ -0,0 +1,26 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/cxx_exprs.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx_exprs.h
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s
+
+int integer;
+double floating;
+char character;
+
+// CXXStaticCastExpr
+static_cast_result void_ptr = &integer;
+
+// CXXDynamicCastExpr
+Derived *d;
+dynamic_cast_result derived_ptr = d;
+
+// CXXReinterpretCastExpr
+reinterpret_cast_result void_ptr2 = &integer;
+
+// CXXConstCastExpr
+const_cast_result char_ptr = &character;
+
+// CXXFunctionalCastExpr
+functional_cast_result *double_ptr = &floating;
diff --git a/test/PCH/cxx_exprs.h b/test/PCH/cxx_exprs.h
new file mode 100644
index 000000000000..b64942849419
--- /dev/null
+++ b/test/PCH/cxx_exprs.h
@@ -0,0 +1,21 @@
+// Header for PCH test cxx_exprs.cpp
+
+// CXXStaticCastExpr
+typedef typeof(static_cast<void *>(0)) static_cast_result;
+
+// CXXDynamicCastExpr
+struct Base { virtual void f(); };
+struct Derived : Base { };
+Base *base_ptr;
+typedef typeof(dynamic_cast<Derived *>(base_ptr)) dynamic_cast_result;
+
+// CXXReinterpretCastExpr
+typedef typeof(reinterpret_cast<void *>(0)) reinterpret_cast_result;
+
+// CXXConstCastExpr
+const char *const_char_ptr_value;
+typedef typeof(const_cast<char *>(const_char_ptr_value)) const_cast_result;
+
+// CXXFunctionalCastExpr
+int int_value;
+typedef typeof(double(int_value)) functional_cast_result;
diff --git a/test/Preprocessor/foo.framework/Headers/bar.h b/test/Preprocessor/foo.framework/Headers/bar.h
deleted file mode 100644
index 574e851bb3e6..000000000000
--- a/test/Preprocessor/foo.framework/Headers/bar.h
+++ /dev/null
@@ -1,3 +0,0 @@
-
-int y;
-
diff --git a/test/Preprocessor/foo.framework/Headers/foo.h b/test/Preprocessor/foo.framework/Headers/foo.h
deleted file mode 100644
index b08d948fabff..000000000000
--- a/test/Preprocessor/foo.framework/Headers/foo.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// This should warn: published framework headers should always
-// #import headers within the framework with framework paths.
-#include "bar.h"
-
-int x;
-
diff --git a/test/Preprocessor/framework-include.m b/test/Preprocessor/framework-include.m
deleted file mode 100644
index 7e50f18f39b4..000000000000
--- a/test/Preprocessor/framework-include.m
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %clang -E -F%S %s 2>&1 | grep "published framework headers should always #import headers within the framework with framework paths"
-
-// rdar://7520940
-#include <foo/foo.h>
-
diff --git a/test/Rewriter/rewrite-byref-vars.mm b/test/Rewriter/rewrite-byref-vars.mm
index 581437b5a5df..1489c5947293 100644
--- a/test/Rewriter/rewrite-byref-vars.mm
+++ b/test/Rewriter/rewrite-byref-vars.mm
@@ -31,5 +31,16 @@ __declspec(dllexport) extern "C" __declspec(dllexport) void XXXXBreakTheRewriter
}
+@interface I
+{
+ id list;
+}
+- (void) Meth;
+@end
+
+@implementation I
+- (void) Meth { __attribute__((__blocks__(byref))) void ** listp = (void **)list; }
+@end
+
// $CLANG -cc1 -fms-extensions -rewrite-objc -x objective-c++ -fblocks bug.mm
// g++ -c -D"__declspec(X)=" bug.cpp
diff --git a/test/Rewriter/rewrite-extern-c.mm b/test/Rewriter/rewrite-extern-c.mm
new file mode 100644
index 000000000000..1c8e90faed9f
--- /dev/null
+++ b/test/Rewriter/rewrite-extern-c.mm
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -x objective-c++ -fblocks -rewrite-objc -o - %s
+// radar 7546096
+
+extern "C" {
+ short foo() { }
+}
+typedef unsigned char Boolean;
+
diff --git a/test/Rewriter/rewrite-protocol-type-1.m b/test/Rewriter/rewrite-protocol-type-1.m
index 902559dca600..2bdf8e462223 100644
--- a/test/Rewriter/rewrite-protocol-type-1.m
+++ b/test/Rewriter/rewrite-protocol-type-1.m
@@ -22,3 +22,6 @@ INTF <MyProto1, MyProto2> * Func1(INTF *p2, INTF<MyProto1, MyProto2> *p3, INTF *
return p3;
}
+@interface Foo
+@property int (*hashFunction)(const void *item, int (*size)(const void *item));
+@end
diff --git a/test/Rewriter/rewrite-typeof.mm b/test/Rewriter/rewrite-typeof.mm
new file mode 100644
index 000000000000..f95cd9ac7c76
--- /dev/null
+++ b/test/Rewriter/rewrite-typeof.mm
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc -o - %s
+
+extern "C" {
+extern "C" void *_Block_copy(const void *aBlock);
+extern "C" void _Block_release(const void *aBlock);
+}
+
+int main() {
+ __attribute__((__blocks__(byref))) int a = 42;
+ int save_a = a;
+
+ void (^b)(void) = ^{
+ ((__typeof(^{ a = 2; }))_Block_copy((const void *)(^{ a = 2; })));
+ };
+
+ ((__typeof(b))_Block_copy((const void *)(b)));
+
+ return 0;
+}
+
diff --git a/test/Sema/block-literal.c b/test/Sema/block-literal.c
index e9c2341a99c7..c303b8417d94 100644
--- a/test/Sema/block-literal.c
+++ b/test/Sema/block-literal.c
@@ -33,7 +33,8 @@ void test2() {
break; // expected-error {{'break' statement not in loop or switch statement}}
continue; // expected-error {{'continue' statement not in loop statement}}
while(1) break; // ok
- goto foo; // expected-error {{goto not allowed}}
+ goto foo; // expected-error {{use of undeclared label 'foo'}}
+ a: goto a; // ok
});
break;
}
diff --git a/test/Sema/block-misc.c b/test/Sema/block-misc.c
index 52cebfe8922f..1109be6311b0 100644
--- a/test/Sema/block-misc.c
+++ b/test/Sema/block-misc.c
@@ -87,8 +87,7 @@ int test7(void (^p)()) {
void test8() {
somelabel:
- // FIXME: This should say "jump out of block not legal" when gotos are allowed.
- ^{ goto somelabel; }(); // expected-error {{goto not allowed in block literal}}
+ ^{ goto somelabel; }(); // expected-error {{use of undeclared label 'somelabel'}}
}
void test9() {
diff --git a/test/Sema/compound-literal.c b/test/Sema/compound-literal.c
index a650d12de973..0c8ddd42d0c8 100644
--- a/test/Sema/compound-literal.c
+++ b/test/Sema/compound-literal.c
@@ -31,3 +31,6 @@ void IncompleteFunc(unsigned x) {
(void){1,2,3}; // -expected-error {{variable has incomplete type}}
(void(void)) { 0 }; // -expected-error{{illegal initializer type 'void (void)'}}
}
+
+// PR6080
+int array[(sizeof(int[3]) == sizeof( (int[]) {0,1,2} )) ? 1 : -1];
diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c
index 4d3f6cbcf2b8..74bc7c46f8f5 100644
--- a/test/Sema/scope-check.c
+++ b/test/Sema/scope-check.c
@@ -181,15 +181,14 @@ void test11(int n) {
// TODO: When and if gotos are allowed in blocks, this should work.
void test12(int n) {
void *P = ^{
- goto L1; // expected-error {{goto not allowed in block literal}}
+ goto L1;
L1:
- goto L2; // expected-error {{goto not allowed in block literal}}
+ goto L2;
L2:
- goto L3; // expected-error {{goto not allowed in block literal}}
- // todo-error {{illegal goto into protected scope}}
- int Arr[n]; // todo-note {{jump bypasses initialization of variable length array}}
+ goto L3; // expected-error {{illegal goto into protected scope}}
+ int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}}
L3:
- goto L4; // expected-error {{goto not allowed in block literal}}
+ goto L4;
L4: return;
};
}
diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c
index 2c123d0b0fc4..1eef63713360 100644
--- a/test/Sema/warn-unreachable.c
+++ b/test/Sema/warn-unreachable.c
@@ -1,4 +1,8 @@
-// RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code
+// RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code -Wno-unused-value
+
+int halt() __attribute__((noreturn));
+int live();
+int dead();
void test1() {
goto c;
@@ -18,3 +22,79 @@ void test1() {
goto d;
f: ;
}
+
+void test2() {
+ int i;
+ switch (live()) {
+ case 1:
+ halt(),
+ dead(); // expected-warning {{will never be executed}}
+
+ case 2:
+ live(), halt(),
+ dead(); // expected-warning {{will never be executed}}
+
+ case 3:
+ live()
+ + // expected-warning {{will never be executed}}
+ halt();
+ dead();
+
+ case 4:
+ a4:
+ live(),
+ halt();
+ goto a4; // expected-warning {{will never be executed}}
+
+ case 5:
+ goto a5;
+ c5:
+ dead(); // expected-warning {{will never be executed}}
+ goto b5;
+ a5:
+ live(),
+ halt();
+ b5:
+ goto c5;
+
+ case 6:
+ if (live())
+ goto e6;
+ live(),
+ halt();
+ d6:
+ dead(); // expected-warning {{will never be executed}}
+ goto b6;
+ c6:
+ dead();
+ goto b6;
+ e6:
+ live(),
+ halt();
+ b6:
+ goto c6;
+ case 7:
+ halt()
+ + // expected-warning {{will never be executed}}
+ dead();
+ - // expected-warning {{will never be executed}}
+ halt();
+ case 8:
+ i
+ += // expected-warning {{will never be executed}}
+ halt();
+ case 9:
+ halt()
+ ? // expected-warning {{will never be executed}}
+ dead() : dead();
+ case 10:
+ ( // expected-warning {{will never be executed}}
+ float)halt();
+ case 11: {
+ int a[5];
+ live(),
+ a[halt()
+ ]; // expected-warning {{will never be executed}}
+ }
+ }
+}
diff --git a/test/SemaCXX/access-control-check.cpp b/test/SemaCXX/access-control-check.cpp
index e6e261c1a89f..cf2d191a294f 100644
--- a/test/SemaCXX/access-control-check.cpp
+++ b/test/SemaCXX/access-control-check.cpp
@@ -5,12 +5,11 @@ class M {
};
class P {
- int iP;
- int PPR();
+ int iP; // expected-note {{declared private here}}
+ int PPR(); // expected-note {{declared private here}}
};
class N : M,P {
N() {}
- // FIXME. No access violation is reported in method call or member access.
- int PR() { return iP + PPR(); }
+ int PR() { return iP + PPR(); } // expected-error 2 {{access to private member of 'class P'}}
};
diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp
index 374241c9e4e6..0590db28d832 100644
--- a/test/SemaCXX/anonymous-union.cpp
+++ b/test/SemaCXX/anonymous-union.cpp
@@ -111,3 +111,13 @@ struct BadMembers {
// <rdar://problem/6481130>
typedef union { }; // expected-error{{declaration does not declare anything}}
+
+// <rdar://problem/7562438>
+typedef struct objc_module *Foo ;
+
+typedef struct _s {
+ union {
+ int a;
+ int Foo;
+ };
+} s, *ps;
diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp
index f1b02f5d4c6d..47ae06ab0e69 100644
--- a/test/SemaCXX/enum.cpp
+++ b/test/SemaCXX/enum.cpp
@@ -56,3 +56,14 @@ namespace test1 {
enum enum4 { v4 = __LONG_MAX__ * 2UL };
int test4[is_same<__typeof(+v4), unsigned long>::value];
}
+
+// PR6061
+namespace PR6061 {
+ struct A { enum { id }; };
+ struct B { enum { id }; };
+
+ struct C : public A, public B
+ {
+ enum { id };
+ };
+}
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 0e0f630bc497..b058fc13d96f 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -65,7 +65,7 @@ void bad_news(int *ip)
(void)new S(1); // expected-error {{no matching constructor}}
(void)new S(1, 1); // expected-error {{call to constructor of 'struct S' is ambiguous}}
(void)new const int; // expected-error {{default initialization of an object of const type 'int const'}}
- (void)new float*(ip); // expected-error {{cannot initialize a value of type 'float *' with an lvalue of type 'int *'}}
+ (void)new float*(ip); // expected-error {{cannot initialize a new value of type 'float *' with an lvalue of type 'int *'}}
// Undefined, but clang should reject it directly.
(void)new int[-1]; // expected-error {{array size is negative}}
(void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}}
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index d20bf23b8fd9..12dc5daccb6d 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -333,3 +333,17 @@ namespace test2 {
inline bool operator!=(const qrgb666 &v) const { return !(*this == v); }
};
}
+
+// PR 6117
+namespace test3 {
+ struct Base {};
+ struct Incomplete;
+
+ void foo(Base *); // expected-note 2 {{cannot convert argument of incomplete type}}
+ void foo(Base &); // expected-note 2 {{cannot convert argument of incomplete type}}
+
+ void test(Incomplete *P) {
+ foo(P); // expected-error {{no matching function for call to 'foo'}}
+ foo(*P); // expected-error {{no matching function for call to 'foo'}}
+ }
+}
diff --git a/test/SemaCXX/unused.cpp b/test/SemaCXX/unused.cpp
index 6fd108186afa..88783ce1a6b3 100644
--- a/test/SemaCXX/unused.cpp
+++ b/test/SemaCXX/unused.cpp
@@ -13,3 +13,12 @@ APSInt& APSInt::operator=(const APSInt &RHS) {
APInt::operator=(RHS);
return *this;
}
+
+template<typename T>
+struct X {
+ X();
+};
+
+void test() {
+ X<int>();
+}
diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp
index 4fdac85040be..5e1e9b0899c6 100644
--- a/test/SemaCXX/virtual-override.cpp
+++ b/test/SemaCXX/virtual-override.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s
+// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s -std=c++0x
namespace T1 {
class A {
@@ -197,3 +197,59 @@ namespace PR5920 {
virtual Derived<int>* Method();
};
}
+
+// Look through template types and typedefs to see whether return types are
+// pointers or references.
+namespace PR6110 {
+ class Base {};
+ class Derived : public Base {};
+
+ typedef Base* BaseP;
+ typedef Derived* DerivedP;
+
+ class X { virtual BaseP f(); };
+ class X1 : public X { virtual DerivedP f(); };
+
+ template <typename T> class Y { virtual T f(); };
+ template <typename T1, typename T> class Y1 : public Y<T> { virtual T1 f(); };
+ Y1<Derived*, Base*> y;
+}
+
+namespace T10 {
+ struct A { };
+ struct B : A { };
+
+ struct C {
+ virtual A&& f();
+ };
+
+ struct D : C {
+ virtual B&& f();
+ };
+};
+
+namespace T11 {
+ struct A { };
+ struct B : A { };
+
+ struct C {
+ virtual A& f(); // expected-note {{overridden virtual function is here}}
+ };
+
+ struct D : C {
+ virtual B&& f(); // expected-error {{virtual function 'f' has a different return type ('struct T11::B &&') than the function it overrides (which has return type 'struct T11::A &')}}
+ };
+};
+
+namespace T12 {
+ struct A { };
+ struct B : A { };
+
+ struct C {
+ virtual A&& f(); // expected-note {{overridden virtual function is here}}
+ };
+
+ struct D : C {
+ virtual B& f(); // expected-error {{virtual function 'f' has a different return type ('struct T12::B &') than the function it overrides (which has return type 'struct T12::A &&')}}
+ };
+};
diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp
new file mode 100644
index 000000000000..a7ed91d6e27b
--- /dev/null
+++ b/test/SemaCXX/warn-unreachable.cpp
@@ -0,0 +1,76 @@
+// RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code -Wno-unused-value
+
+int &halt() __attribute__((noreturn));
+int &live();
+int dead();
+int liveti() throw(int);
+int (*livetip)() throw(int);
+
+int test1() {
+ try {
+ live();
+ } catch (int i) {
+ live();
+ }
+ return 1;
+}
+
+void test2() {
+ try {
+ live();
+ } catch (int i) {
+ live();
+ }
+ try {
+ liveti();
+ } catch (int i) {
+ live();
+ }
+ try {
+ livetip();
+ } catch (int i) {
+ live();
+ }
+ throw 1;
+ dead(); // expected-warning {{will never be executed}}
+}
+
+
+void test3() {
+ halt()
+ --; // expected-warning {{will never be executed}}
+ halt()
+ ? // expected-warning {{will never be executed}}
+ dead() : dead();
+ live(),
+ float // expected-warning {{will never be executed}}
+ (halt());
+}
+
+void test4() {
+ struct S {
+ int mem;
+ } s;
+ S &foor();
+ halt(), foor()
+ .mem; // expected-warning {{will never be executed}}
+}
+
+void test5() {
+ struct S {
+ int mem;
+ } s;
+ S &foor() __attribute__((noreturn));
+ foor()
+ .mem; // expected-warning {{will never be executed}}
+}
+
+void test6() {
+ struct S {
+ ~S() { }
+ S(int i) { }
+ };
+ live(),
+ S // expected-warning {{will never be executed}}
+ (halt());
+}
diff --git a/test/SemaObjC/method-unused-attribute.m b/test/SemaObjC/method-unused-attribute.m
new file mode 100644
index 000000000000..a4e53210c251
--- /dev/null
+++ b/test/SemaObjC/method-unused-attribute.m
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify %s
+
+@interface INTF
+- (void) correct_use_of_unused: (void *) notice : (id)another_arg;
+- (void) will_warn_unused_arg: (void *) notice : (id)warn_unused;
+- (void) unused_attr_on_decl_ignored: (void *) __attribute__((unused)) will_warn;
+@end
+
+@implementation INTF
+- (void) correct_use_of_unused: (void *) __attribute__((unused)) notice : (id) __attribute__((unused)) newarg{
+}
+- (void) will_warn_unused_arg: (void *) __attribute__((unused)) notice : (id)warn_unused {} // expected-warning {{unused parameter 'warn_unused'}}
+- (void) unused_attr_on_decl_ignored: (void *) will_warn{} // expected-warning {{unused parameter 'will_warn'}}
+@end
+
diff --git a/test/SemaObjC/property-category-2.m b/test/SemaObjC/property-category-2.m
index f258b2c25012..e63672bb0ad7 100644
--- a/test/SemaObjC/property-category-2.m
+++ b/test/SemaObjC/property-category-2.m
@@ -4,7 +4,8 @@
@protocol MyProtocol
@property float myFloat;
-@property float anotherFloat;
+@property float anotherFloat; // expected-warning {{property 'anotherFloat' requires method 'anotherFloat' to be defined - use @dynamic}} \
+ // expected-warning {{property 'anotherFloat' requires method 'setAnotherFloat:' to be defined }}
@end
@interface MyObject { float anotherFloat; }
@@ -13,7 +14,7 @@
@interface MyObject (CAT) <MyProtocol>
@end
-@implementation MyObject (CAT)
+@implementation MyObject (CAT) // expected-note 2 {{implementation is here}}
@dynamic myFloat; // OK
@synthesize anotherFloat; // expected-error {{@synthesize not allowed in a category's implementation}}
@end
diff --git a/test/SemaObjC/property-category-impl.m b/test/SemaObjC/property-category-impl.m
new file mode 100644
index 000000000000..997949778c6e
--- /dev/null
+++ b/test/SemaObjC/property-category-impl.m
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+/* This test is for categories which don't implement the accessors but some accessors are
+ implemented in their base class implementation. In this case,no warning must be issued.
+*/
+
+@interface MyClass
+{
+ int _foo;
+}
+@property(readonly) int foo;
+@end
+
+@implementation MyClass
+- (int) foo { return _foo; }
+@end
+
+@interface MyClass (private)
+@property(readwrite) int foo;
+@end
+
+@implementation MyClass (private)
+- (void) setFoo:(int)foo { _foo = foo; }
+@end
+
+@interface MyClass (public)
+@property(readwrite) int foo; // expected-warning {{property 'foo' requires method 'setFoo:' to be defined }}
+@end
+
+@implementation MyClass (public)// expected-note {{implementation is here}}
+@end
diff --git a/test/SemaObjC/property-user-setter.m b/test/SemaObjC/property-user-setter.m
index c06f2b6f44fb..babccee4a7f0 100644
--- a/test/SemaObjC/property-user-setter.m
+++ b/test/SemaObjC/property-user-setter.m
@@ -80,11 +80,24 @@ static int g_val;
}
@end
+@interface C {}
+// - (int)Foo;
+- (void)setFoo:(int)value;
+@end
+
+void g(int);
+
+void f(C *c) {
+ c.Foo = 17; // expected-error {{property 'Foo' not found on object of type 'C *'}}
+ g(c.Foo); // expected-error {{property 'Foo' not found on object of type 'C *'}}
+}
+
+
void abort(void);
int main (void) {
Subclass *x = [[Subclass alloc] init];
- x.setterOnly = 4;
+ x.setterOnly = 4; // expected-error {{property 'setterOnly' not found on object of type 'Subclass *'}}
if (g_val != 4)
abort ();
return 0;
diff --git a/test/SemaObjC/property.m b/test/SemaObjC/property.m
index bc2056c97911..b7f0fcaa7629 100644
--- a/test/SemaObjC/property.m
+++ b/test/SemaObjC/property.m
@@ -11,7 +11,8 @@
@end
@interface I(CAT)
-@property int d1;
+@property int d1; // expected-warning {{property 'd1' requires method 'd1' to be defined }} \
+ // expected-warning {{property 'd1' requires method 'setD1:' to be defined }}
@end
@implementation I
@@ -22,7 +23,7 @@
@synthesize name; // OK! property with same name as an accessible ivar of same name
@end
-@implementation I(CAT)
+@implementation I(CAT) // expected-note 2 {{implementation is here}}
@synthesize d1; // expected-error {{@synthesize not allowed in a category's implementation}}
@dynamic bad; // expected-error {{property implementation must have its declaration in the category 'CAT'}}
@end
diff --git a/test/SemaObjC/super.m b/test/SemaObjC/super.m
index 3b8697288a3a..a61d72fda5ac 100644
--- a/test/SemaObjC/super.m
+++ b/test/SemaObjC/super.m
@@ -39,3 +39,10 @@ void f0(int super) {
void f1(int puper) {
[super m]; // expected-error{{use of undeclared identifier 'super'}}
}
+
+// radar 7400691
+typedef Foo super;
+
+void test() {
+ [super cMethod];
+}
diff --git a/test/SemaObjC/unimplemented-protocol-prop.m b/test/SemaObjC/unimplemented-protocol-prop.m
new file mode 100644
index 000000000000..d3de50efea58
--- /dev/null
+++ b/test/SemaObjC/unimplemented-protocol-prop.m
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@protocol PROTOCOL0
+@required
+@property float MyProperty0; // expected-warning {{property 'MyProperty0' requires method 'MyProperty0' to be defined }} \
+ // expected-warning {{property 'MyProperty0' requires method 'setMyProperty0:' to be defined}}
+@end
+
+@protocol PROTOCOL<PROTOCOL0>
+@required
+@property float MyProperty; // expected-warning {{property 'MyProperty' requires method 'MyProperty' to be defined}} \
+ // expected-warning {{property 'MyProperty' requires method 'setMyProperty:' to be defined}}
+@optional
+@property float OptMyProperty;
+@end
+
+@interface I <PROTOCOL>
+@end
+
+@implementation I @end // expected-note 4 {{implementation is here}}
diff --git a/test/SemaObjCXX/cstyle-block-pointer-cast.mm b/test/SemaObjCXX/cstyle-block-pointer-cast.mm
new file mode 100644
index 000000000000..72f5283dea37
--- /dev/null
+++ b/test/SemaObjCXX/cstyle-block-pointer-cast.mm
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
+// radar 7562285
+
+typedef int (^blocktype)(int a, int b);
+
+@interface A {
+ A* a;
+ id b;
+ Class c;
+}
+- (blocktype)Meth;
+@end
+
+@implementation A
+- (blocktype)Meth {
+ if (b)
+ return (blocktype)b;
+ else if (a)
+ return (blocktype)a; // expected-error {{C-style cast from 'A *' to 'blocktype' (aka 'int (^)(int, int)') is not allowed}}
+ else
+ return (blocktype)c;
+}
+@end
+
+@interface B {
+ blocktype a;
+ blocktype b;
+ blocktype c;
+}
+- (id)Meth;
+@end
+
+@implementation B
+- (id)Meth {
+ if (a)
+ return (A*)a; // expected-error {{C-style cast from 'blocktype' (aka 'int (^)(int, int)') to 'A *' is not allowed}}
+ if (b)
+ return (id)b;
+ if (c)
+ return (Class)b;
+}
+@end
diff --git a/test/SemaObjCXX/pointer-to-objc-pointer-conv.mm b/test/SemaObjCXX/pointer-to-objc-pointer-conv.mm
new file mode 100644
index 000000000000..80383ebfd8a9
--- /dev/null
+++ b/test/SemaObjCXX/pointer-to-objc-pointer-conv.mm
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@interface G
+@end
+
+@interface F
+- (void)bar:(id *)objects;
+- (void)foo:(G**)objects;
+@end
+
+
+void a() {
+ F *b;
+ G **keys;
+ [b bar:keys];
+
+ id *PID;
+ [b foo:PID];
+
+}
+
diff --git a/test/SemaTemplate/dependent-base-classes.cpp b/test/SemaTemplate/dependent-base-classes.cpp
index 79b28c2239fe..80d20b09b82a 100644
--- a/test/SemaTemplate/dependent-base-classes.cpp
+++ b/test/SemaTemplate/dependent-base-classes.cpp
@@ -82,3 +82,31 @@ namespace Ambig {
Derived<int> di; // expected-note{{instantiation of}}
}
+
+namespace PR6081 {
+ template<typename T>
+ struct A { };
+
+ template<typename T>
+ class B : public A<T>
+ {
+ public:
+ template< class X >
+ void f0(const X & k)
+ {
+ this->template f1<int>()(k);
+ }
+ };
+
+ template<typename T>
+ class C
+ {
+ public:
+ template< class X >
+ void f0(const X & k)
+ {
+ this->template f1<int>()(k); // expected-error{{'f1' following the 'template' keyword does not refer to a template}} \
+ // FIXME: expected-error{{unqualified-id}}
+ }
+ };
+}
diff --git a/test/SemaTemplate/dependent-base-member-init.cpp b/test/SemaTemplate/dependent-base-member-init.cpp
index c9823d227d4c..1f131491e621 100644
--- a/test/SemaTemplate/dependent-base-member-init.cpp
+++ b/test/SemaTemplate/dependent-base-member-init.cpp
@@ -34,3 +34,26 @@ template<typename T> struct s1 : s0<typename s0_traits<T>::t0> {
s1() {}
};
+// PR6062
+namespace PR6062 {
+ template <typename T>
+ class A : public T::type
+ {
+ A() : T::type()
+ {
+ }
+
+ template <typename U>
+ A(U const& init)
+ : T::type(init)
+ { }
+
+ template<typename U>
+ A(U& init) : U::other_type(init) { }
+ };
+}
+
+template<typename T, typename U>
+struct X0 : T::template apply<U> {
+ X0(int i) : T::template apply<U>(i) { }
+};
diff --git a/test/SemaTemplate/dependent-expr.cpp b/test/SemaTemplate/dependent-expr.cpp
index 412a811f7292..3f481b513691 100644
--- a/test/SemaTemplate/dependent-expr.cpp
+++ b/test/SemaTemplate/dependent-expr.cpp
@@ -5,3 +5,22 @@ template <typename Iterator>
void Test(Iterator it) {
*(it += 1);
}
+
+namespace PR6045 {
+ template<unsigned int r>
+ class A
+ {
+ static const unsigned int member = r;
+ void f();
+ };
+
+ template<unsigned int r>
+ const unsigned int A<r>::member;
+
+ template<unsigned int r>
+ void A<r>::f()
+ {
+ unsigned k;
+ (void)(k % member);
+ }
+}
diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp
index 05289b10d26c..8bc2631e119f 100644
--- a/test/SemaTemplate/friend-template.cpp
+++ b/test/SemaTemplate/friend-template.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-
// PR5057
namespace test0 {
namespace std {
@@ -107,3 +106,20 @@ namespace test5 {
template <typename T> friend struct cache;
};
}
+
+// PR6022
+namespace PR6022 {
+ template <class T1, class T2 , class T3 > class A;
+
+ namespace inner {
+ template<class T1, class T2, class T3, class T>
+ A<T1, T2, T3>& f0(A<T1, T2, T3>&, T);
+ }
+
+ template<class T1, class T2, class T3>
+ class A {
+ template<class U1, class U2, class U3, class T>
+ friend A<U1, U2, U3>& inner::f0(A<U1, U2, U3>&, T);
+ };
+}
+
diff --git a/test/SemaTemplate/instantiate-local-class.cpp b/test/SemaTemplate/instantiate-local-class.cpp
new file mode 100644
index 000000000000..768eb2170a15
--- /dev/null
+++ b/test/SemaTemplate/instantiate-local-class.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -verify %s
+template<typename T>
+void f0() {
+ struct X;
+ typedef struct Y {
+ T (X::* f1())(int) { return 0; }
+ } Y2;
+
+ Y2 y = Y();
+}
+
+template void f0<int>();
+
+// PR5764
+namespace PR5764 {
+ class X {
+ template <typename T>
+ void Bar() {
+ typedef T ValueType;
+ class Y {
+ Y() { V = ValueType(); }
+
+ ValueType V;
+ };
+
+ Y y;
+ }
+ };
+
+ void test(X x) {
+ x.Bar<int>();
+ }
+}
+
diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp
index 9edefe8b63e0..ea17cdbb5864 100644
--- a/test/SemaTemplate/member-template-access-expr.cpp
+++ b/test/SemaTemplate/member-template-access-expr.cpp
@@ -103,3 +103,23 @@ struct X5 {
this->f<T*>();
}
};
+
+namespace PR6021 {
+ template< class T1, class T2 >
+ class Outer
+ {
+ public: // Range operations
+ template< class X > X tmpl( const X* = 0 ) const;
+
+ struct Inner
+ {
+ const Outer& o;
+
+ template< class X >
+ operator X() const
+ {
+ return o.tmpl<X>();
+ }
+ };
+ };
+}
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 86e0ddc20205..84f908d57183 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -13,10 +13,14 @@
//===----------------------------------------------------------------------===//
#include "CIndexer.h"
+#include "CXCursor.h"
+#include "clang/Basic/Version.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLocVisitor.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Program.h"
@@ -24,6 +28,7 @@
#include <cstdio>
using namespace clang;
+using namespace clang::cxcursor;
using namespace idx;
//===----------------------------------------------------------------------===//
@@ -111,362 +116,744 @@ public:
#endif
#endif
-//===----------------------------------------------------------------------===//
-// Visitors.
-//===----------------------------------------------------------------------===//
+typedef llvm::PointerIntPair<ASTContext *, 1, bool> CXSourceLocationPtr;
-namespace {
-static enum CXCursorKind TranslateDeclRefExpr(DeclRefExpr *DRE) {
- NamedDecl *D = DRE->getDecl();
- if (isa<VarDecl>(D))
- return CXCursor_VarRef;
- else if (isa<FunctionDecl>(D))
- return CXCursor_FunctionRef;
- else if (isa<EnumConstantDecl>(D))
- return CXCursor_EnumConstantRef;
- else
- return CXCursor_NotImplemented;
+/// \brief Translate a Clang source location into a CIndex source location.
+static CXSourceLocation translateSourceLocation(ASTContext &Context,
+ SourceLocation Loc,
+ bool AtEnd = false) {
+ CXSourceLocationPtr Ptr(&Context, AtEnd);
+ CXSourceLocation Result = { Ptr.getOpaqueValue(), Loc.getRawEncoding() };
+ return Result;
}
-#if 0
-// Will be useful one day.
-class CRefVisitor : public StmtVisitor<CRefVisitor> {
- CXDecl CDecl;
- CXDeclIterator Callback;
- CXClientData CData;
-
- void Call(enum CXCursorKind CK, Stmt *SRef) {
- CXCursor C = { CK, CDecl, SRef };
- Callback(CDecl, C, CData);
- }
+/// \brief Translate a Clang source range into a CIndex source range.
+static CXSourceRange translateSourceRange(ASTContext &Context, SourceRange R) {
+ CXSourceRange Result = { &Context,
+ R.getBegin().getRawEncoding(),
+ R.getEnd().getRawEncoding() };
+ return Result;
+}
-public:
- CRefVisitor(CXDecl C, CXDeclIterator cback, CXClientData D) :
- CDecl(C), Callback(cback), CData(D) {}
+static SourceLocation translateSourceLocation(CXSourceLocation L) {
+ return SourceLocation::getFromRawEncoding(L.int_data);
+}
- void VisitStmt(Stmt *S) {
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
- C != CEnd; ++C)
- Visit(*C);
- }
- void VisitDeclRefExpr(DeclRefExpr *Node) {
- Call(TranslateDeclRefExpr(Node), Node);
- }
- void VisitMemberExpr(MemberExpr *Node) {
- Call(CXCursor_MemberRef, Node);
- }
- void VisitObjCMessageExpr(ObjCMessageExpr *Node) {
- Call(CXCursor_ObjCSelectorRef, Node);
- }
- void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
- Call(CXCursor_ObjCIvarRef, Node);
- }
+static SourceRange translateSourceRange(CXSourceRange R) {
+ return SourceRange(SourceLocation::getFromRawEncoding(R.begin_int_data),
+ SourceLocation::getFromRawEncoding(R.end_int_data));
+}
+
+/// \brief The result of comparing two source ranges.
+enum RangeComparisonResult {
+ /// \brief Either the ranges overlap or one of the ranges is invalid.
+ RangeOverlap,
+
+ /// \brief The first range ends before the second range starts.
+ RangeBefore,
+
+ /// \brief The first range starts after the second range ends.
+ RangeAfter
};
-#endif
-// Translation Unit Visitor.
+/// \brief Compare two source ranges to determine their relative position in
+/// the translation unit.
+static RangeComparisonResult RangeCompare(SourceManager &SM,
+ SourceRange R1,
+ SourceRange R2) {
+ assert(R1.isValid() && "First range is invalid?");
+ assert(R2.isValid() && "Second range is invalid?");
+ if (SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
+ return RangeBefore;
+ if (SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
+ return RangeAfter;
+ return RangeOverlap;
+}
-class TUVisitor : public DeclVisitor<TUVisitor> {
-public:
- typedef void (*Iterator)(void *, CXCursor, CXClientData);
-private:
- void *Root; // CXDecl or CXTranslationUnit
- Iterator Callback; // CXTranslationUnitIterator or CXDeclIterator.
- CXClientData CData;
+//===----------------------------------------------------------------------===//
+// Cursor visitor.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+// Cursor visitor.
+class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
+ public TypeLocVisitor<CursorVisitor, bool>,
+ public StmtVisitor<CursorVisitor, bool>
+{
+ /// \brief The translation unit we are traversing.
+ ASTUnit *TU;
+
+ /// \brief The parent cursor whose children we are traversing.
+ CXCursor Parent;
+
+ /// \brief The declaration that serves at the parent of any statement or
+ /// expression nodes.
+ Decl *StmtParent;
+
+ /// \brief The visitor function.
+ CXCursorVisitor Visitor;
+
+ /// \brief The opaque client data, to be passed along to the visitor.
+ CXClientData ClientData;
+
// MaxPCHLevel - the maximum PCH level of declarations that we will pass on
// to the visitor. Declarations with a PCH level greater than this value will
// be suppressed.
unsigned MaxPCHLevel;
- void Call(enum CXCursorKind CK, NamedDecl *ND) {
- // Filter any declarations that have a PCH level greater than what we allow.
- if (ND->getPCHLevel() > MaxPCHLevel)
- return;
+ /// \brief When valid, a source range to which the cursor should restrict
+ /// its search.
+ SourceRange RegionOfInterest;
+
+ using DeclVisitor<CursorVisitor, bool>::Visit;
+ using TypeLocVisitor<CursorVisitor, bool>::Visit;
+ using StmtVisitor<CursorVisitor, bool>::Visit;
+
+ /// \brief Determine whether this particular source range comes before, comes
+ /// after, or overlaps the region of interest.
+ ///
+ /// \param R a source range retrieved from the abstract syntax tree.
+ RangeComparisonResult CompareRegionOfInterest(SourceRange R);
+
+ /// \brief Determine whether this particular source range comes before, comes
+ /// after, or overlaps the region of interest.
+ ///
+ /// \param CXR a source range retrieved from a cursor.
+ RangeComparisonResult CompareRegionOfInterest(CXSourceRange CXR);
+
+public:
+ CursorVisitor(ASTUnit *TU, CXCursorVisitor Visitor, CXClientData ClientData,
+ unsigned MaxPCHLevel,
+ SourceRange RegionOfInterest = SourceRange())
+ : TU(TU), Visitor(Visitor), ClientData(ClientData),
+ MaxPCHLevel(MaxPCHLevel), RegionOfInterest(RegionOfInterest)
+ {
+ Parent.kind = CXCursor_NoDeclFound;
+ Parent.data[0] = 0;
+ Parent.data[1] = 0;
+ Parent.data[2] = 0;
+ StmtParent = 0;
+ }
+
+ bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
+ bool VisitChildren(CXCursor Parent);
+
+ // Declaration visitors
+ bool VisitDeclContext(DeclContext *DC);
+ bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ bool VisitTypedefDecl(TypedefDecl *D);
+ bool VisitTagDecl(TagDecl *D);
+ bool VisitEnumConstantDecl(EnumConstantDecl *D);
+ bool VisitDeclaratorDecl(DeclaratorDecl *DD);
+ bool VisitFunctionDecl(FunctionDecl *ND);
+ bool VisitFieldDecl(FieldDecl *D);
+ bool VisitVarDecl(VarDecl *);
+ bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
+ bool VisitObjCContainerDecl(ObjCContainerDecl *D);
+ bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
+ bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
+ bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+ bool VisitObjCImplDecl(ObjCImplDecl *D);
+ bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+ bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+ // FIXME: ObjCPropertyDecl requires TypeSourceInfo, getter/setter locations,
+ // etc.
+ // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
+ bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
+ bool VisitObjCClassDecl(ObjCClassDecl *D);
+
+ // Type visitors
+ // FIXME: QualifiedTypeLoc doesn't provide any location information
+ bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
+ bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
+ bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
+ bool VisitTagTypeLoc(TagTypeLoc TL);
+ // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information
+ bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
+ bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
+ bool VisitPointerTypeLoc(PointerTypeLoc TL);
+ bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL);
+ bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
+ bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
+ bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
+ bool VisitFunctionTypeLoc(FunctionTypeLoc TL);
+ bool VisitArrayTypeLoc(ArrayTypeLoc TL);
+ // FIXME: Implement for TemplateSpecializationTypeLoc
+ // FIXME: Implement visitors here when the unimplemented TypeLocs get
+ // implemented
+ bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
+ bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
+
+ // Statement visitors
+ bool VisitStmt(Stmt *S);
+ bool VisitDeclStmt(DeclStmt *S);
+ // FIXME: LabelStmt label?
+ bool VisitIfStmt(IfStmt *S);
+ bool VisitSwitchStmt(SwitchStmt *S);
+
+ // Expression visitors
+ bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ bool VisitExplicitCastExpr(ExplicitCastExpr *E);
+ bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+};
+
+} // end anonymous namespace
- // Filter any implicit declarations (since the source info will be bogus).
- if (ND->isImplicit())
- return;
+RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
+ assert(RegionOfInterest.isValid() && "RangeCompare called with invalid range");
+ if (R.isInvalid())
+ return RangeOverlap;
+
+ // Move the end of the input range to the end of the last token in that
+ // range.
+ R.setEnd(TU->getPreprocessor().getLocForEndOfToken(R.getEnd(), 1));
+ return RangeCompare(TU->getSourceManager(), R, RegionOfInterest);
+}
+
+RangeComparisonResult CursorVisitor::CompareRegionOfInterest(CXSourceRange CXR) {
+ return CompareRegionOfInterest(translateSourceRange(CXR));
+}
+
+/// \brief Visit the given cursor and, if requested by the visitor,
+/// its children.
+///
+/// \param Cursor the cursor to visit.
+///
+/// \param CheckRegionOfInterest if true, then the caller already checked that
+/// this cursor is within the region of interest.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
+ if (clang_isInvalid(Cursor.kind))
+ return false;
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ Decl *D = getCursorDecl(Cursor);
+ assert(D && "Invalid declaration cursor");
+ if (D->getPCHLevel() > MaxPCHLevel)
+ return false;
+
+ if (D->isImplicit())
+ return false;
+ }
- CXCursor C = { CK, ND, 0, 0 };
- Callback(Root, C, CData);
+ // If we have a range of interest, and this cursor doesn't intersect with it,
+ // we're done.
+ if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
+ CXSourceRange Range = clang_getCursorExtent(Cursor);
+ if (translateSourceRange(Range).isInvalid() ||
+ CompareRegionOfInterest(Range))
+ return false;
}
+
+ switch (Visitor(Cursor, Parent, ClientData)) {
+ case CXChildVisit_Break:
+ return true;
-public:
- TUVisitor(void *root, Iterator cback, CXClientData D, unsigned MaxPCHLevel) :
- Root(root), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
-
- void VisitDeclContext(DeclContext *DC);
- void VisitFunctionDecl(FunctionDecl *ND);
- void VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
- void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND);
- void VisitObjCImplementationDecl(ObjCImplementationDecl *ND);
- void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND);
- void VisitObjCProtocolDecl(ObjCProtocolDecl *ND);
- void VisitTagDecl(TagDecl *ND);
- void VisitTranslationUnitDecl(TranslationUnitDecl *D);
- void VisitTypedefDecl(TypedefDecl *ND);
- void VisitVarDecl(VarDecl *ND);
-};
+ case CXChildVisit_Continue:
+ return false;
-void TUVisitor::VisitDeclContext(DeclContext *DC) {
- for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
- I != E; ++I)
- Visit(*I);
+ case CXChildVisit_Recurse:
+ return VisitChildren(Cursor);
+ }
+
+ llvm_unreachable("Silly GCC, we can't get here");
}
+
+/// \brief Visit the children of the given cursor.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::VisitChildren(CXCursor Cursor) {
+ if (clang_isReference(Cursor.kind)) {
+ // By definition, references have no children.
+ return false;
+ }
-void TUVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
- : CXCursor_FunctionDecl, ND);
+ // Set the Parent field to Cursor, then back to its old value once we're
+ // done.
+ class SetParentRAII {
+ CXCursor &Parent;
+ Decl *&StmtParent;
+ CXCursor OldParent;
+
+ public:
+ SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
+ : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
+ {
+ Parent = NewParent;
+ if (clang_isDeclaration(Parent.kind))
+ StmtParent = getCursorDecl(Parent);
+ }
+
+ ~SetParentRAII() {
+ Parent = OldParent;
+ if (clang_isDeclaration(Parent.kind))
+ StmtParent = getCursorDecl(Parent);
+ }
+ } SetParent(Parent, StmtParent, Cursor);
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ Decl *D = getCursorDecl(Cursor);
+ assert(D && "Invalid declaration cursor");
+ return Visit(D);
+ }
+
+ if (clang_isStatement(Cursor.kind))
+ return Visit(getCursorStmt(Cursor));
+ if (clang_isExpression(Cursor.kind))
+ return Visit(getCursorExpr(Cursor));
+
+ if (clang_isTranslationUnit(Cursor.kind)) {
+ ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
+ if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
+ RegionOfInterest.isInvalid()) {
+ const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
+ for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
+ ie = TLDs.end(); it != ie; ++it) {
+ if (Visit(MakeCXCursor(*it, CXXUnit), true))
+ return true;
+ }
+ } else {
+ return VisitDeclContext(
+ CXXUnit->getASTContext().getTranslationUnitDecl());
+ }
+
+ return false;
+ }
+
+ // Nothing to visit at the moment.
+ return false;
}
+
+bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
+ for (DeclContext::decl_iterator
+ I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
+ if (RegionOfInterest.isValid()) {
+ SourceRange R = (*I)->getSourceRange();
+ if (R.isInvalid())
+ continue;
+
+ switch (CompareRegionOfInterest(R)) {
+ case RangeBefore:
+ // This declaration comes before the region of interest; skip it.
+ continue;
+
+ case RangeAfter:
+ // This declaration comes after the region of interest; we're done.
+ return false;
+
+ case RangeOverlap:
+ // This declaration overlaps the region of interest; visit it.
+ break;
+ }
+ }
+
+ if (Visit(MakeCXCursor(*I, TU), true))
+ return true;
+ }
-void TUVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
- Call(CXCursor_ObjCCategoryDecl, ND);
+ return false;
}
-void TUVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
- Call(CXCursor_ObjCCategoryDefn, ND);
+bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ llvm_unreachable("Translation units are visited directly by Visit()");
+ return false;
}
-void TUVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
- Call(CXCursor_ObjCClassDefn, ND);
+bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
+ if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitTagDecl(TagDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ if (Expr *Init = D->getInitExpr())
+ return Visit(MakeCXCursor(Init, StmtParent, TU));
+ return false;
+}
+
+bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+ if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return false;
}
+
+bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
+ if (VisitDeclaratorDecl(ND))
+ return true;
+
+ if (ND->isThisDeclarationADefinition() &&
+ Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+ return true;
-void TUVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
- Call(CXCursor_ObjCInterfaceDecl, ND);
-}
+ return false;
+}
-void TUVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
- Call(CXCursor_ObjCProtocolDecl, ND);
+bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (Expr *BitWidth = D->getBitWidth())
+ return Visit(MakeCXCursor(BitWidth, StmtParent, TU));
+
+ return false;
}
+
+bool CursorVisitor::VisitVarDecl(VarDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
-void TUVisitor::VisitTagDecl(TagDecl *ND) {
- switch (ND->getTagKind()) {
- case TagDecl::TK_struct:
- Call(CXCursor_StructDecl, ND);
- break;
- case TagDecl::TK_class:
- Call(CXCursor_ClassDecl, ND);
- break;
- case TagDecl::TK_union:
- Call(CXCursor_UnionDecl, ND);
- break;
- case TagDecl::TK_enum:
- Call(CXCursor_EnumDecl, ND);
- break;
+ if (Expr *Init = D->getInit())
+ return Visit(MakeCXCursor(Init, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
+ // FIXME: We really need a TypeLoc covering Objective-C method declarations.
+ // At the moment, we don't have information about locations in the return
+ // type.
+ for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
+ PEnd = ND->param_end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU)))
+ return true;
}
+
+ if (ND->isThisDeclarationADefinition() &&
+ Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+ return true;
+
+ return false;
}
+
+bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
+ if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
+ TU)))
+ return true;
-void TUVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+ ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
+ for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
+ E = ND->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(ND);
}
+
+bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
+ ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
+ for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
+ E = PID->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
-void TUVisitor::VisitTypedefDecl(TypedefDecl *ND) {
- Call(CXCursor_TypedefDecl, ND);
+ return VisitObjCContainerDecl(PID);
}
-void TUVisitor::VisitVarDecl(VarDecl *ND) {
- Call(CXCursor_VarDecl, ND);
+bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ // Issue callbacks for super class.
+ if (D->getSuperClass() &&
+ Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
+ D->getSuperClassLoc(),
+ TU)))
+ return true;
+
+ ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
+ for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
+ E = D->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(D);
}
-// Declaration visitor.
-class CDeclVisitor : public DeclVisitor<CDeclVisitor> {
- CXDecl CDecl;
- CXDeclIterator Callback;
- CXClientData CData;
+bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
+ return VisitObjCContainerDecl(D);
+}
- // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
- // to the visitor. Declarations with a PCH level greater than this value will
- // be suppressed.
- unsigned MaxPCHLevel;
+bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ if (Visit(MakeCursorObjCClassRef(D->getCategoryDecl()->getClassInterface(),
+ D->getLocation(), TU)))
+ return true;
+
+ return VisitObjCImplDecl(D);
+}
- void Call(enum CXCursorKind CK, NamedDecl *ND) {
- // Disable the callback when the context is equal to the visiting decl.
- if (CDecl == ND && !clang_isReference(CK))
- return;
+bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+#if 0
+ // Issue callbacks for super class.
+ // FIXME: No source location information!
+ if (D->getSuperClass() &&
+ Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
+ D->getSuperClassLoc(),
+ TU)))
+ return true;
+#endif
+
+ return VisitObjCImplDecl(D);
+}
- // Filter any declarations that have a PCH level greater than what we allow.
- if (ND->getPCHLevel() > MaxPCHLevel)
- return;
+bool CursorVisitor::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+ ObjCForwardProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
+ for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
+ E = D->protocol_end();
+ I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) {
+ for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C)
+ if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ ASTContext &Context = TU->getASTContext();
+
+ // Some builtin types (such as Objective-C's "id", "sel", and
+ // "Class") have associated declarations. Create cursors for those.
+ QualType VisitType;
+ switch (TL.getType()->getAs<BuiltinType>()->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::Bool:
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::UInt128:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ case BuiltinType::WChar:
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ case BuiltinType::LongLong:
+ case BuiltinType::Int128:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ break;
+
+ case BuiltinType::UndeducedAuto: // FIXME: Deserves a cursor?
+ break;
+
+ case BuiltinType::ObjCId:
+ VisitType = Context.getObjCIdType();
+ break;
+
+ case BuiltinType::ObjCClass:
+ VisitType = Context.getObjCClassType();
+ break;
+
+ case BuiltinType::ObjCSel:
+ VisitType = Context.getObjCSelType();
+ break;
+ }
- CXCursor C = { CK, ND, 0, 0 };
- Callback(CDecl, C, CData);
+ if (!VisitType.isNull()) {
+ if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),
+ TU));
}
-public:
- CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D,
- unsigned MaxPCHLevel) :
- CDecl(C), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
-
- void VisitDeclContext(DeclContext *DC);
- void VisitEnumConstantDecl(EnumConstantDecl *ND);
- void VisitFieldDecl(FieldDecl *ND);
- void VisitFunctionDecl(FunctionDecl *ND);
- void VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
- void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
- void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
- void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
- void VisitObjCIvarDecl(ObjCIvarDecl *ND);
- void VisitObjCMethodDecl(ObjCMethodDecl *ND);
- void VisitObjCPropertyDecl(ObjCPropertyDecl *ND);
- void VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
- void VisitParmVarDecl(ParmVarDecl *ND);
- void VisitTagDecl(TagDecl *D);
- void VisitVarDecl(VarDecl *ND);
-};
-} // end anonymous namespace
-void CDeclVisitor::VisitDeclContext(DeclContext *DC) {
- for (DeclContext::decl_iterator
- I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
- Visit(*I);
+ return false;
}
-void CDeclVisitor::VisitEnumConstantDecl(EnumConstantDecl *ND) {
- Call(CXCursor_EnumConstantDecl, ND);
+bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getTypedefDecl(), TL.getNameLoc(), TU));
}
-void CDeclVisitor::VisitFieldDecl(FieldDecl *ND) {
- Call(CXCursor_FieldDecl, ND);
+bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
-void CDeclVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- if (ND->isThisDeclarationADefinition()) {
- VisitDeclContext(dyn_cast<DeclContext>(ND));
-#if 0
- // Not currently needed.
- CompoundStmt *Body = dyn_cast<CompoundStmt>(ND->getBody());
- CRefVisitor RVisit(CDecl, Callback, CData);
- RVisit.Visit(Body);
-#endif
+bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
+ TU)))
+ return true;
}
-}
-void CDeclVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
- // Issue callbacks for the containing class.
- Call(CXCursor_ObjCClassRef, ND);
- // FIXME: Issue callbacks for protocol refs.
- VisitDeclContext(dyn_cast<DeclContext>(ND));
+ return false;
}
-void CDeclVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseTypeLoc()))
+ return true;
+
+ if (TL.hasProtocolsAsWritten()) {
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I),
+ TL.getProtocolLoc(I),
+ TU)))
+ return true;
+ }
+ }
+
+ return false;
}
-void CDeclVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
- // Issue callbacks for super class.
- if (D->getSuperClass())
- Call(CXCursor_ObjCSuperClassRef, D);
-
- for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(),
- E = D->protocol_end(); I != E; ++I)
- Call(CXCursor_ObjCProtocolRef, *I);
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCIvarDecl(ObjCIvarDecl *ND) {
- Call(CXCursor_ObjCIvarDecl, ND);
+bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
- if (ND->getBody()) {
- Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDefn
- : CXCursor_ObjCClassMethodDefn, ND);
- VisitDeclContext(dyn_cast<DeclContext>(ND));
- } else
- Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl
- : CXCursor_ObjCClassMethodDecl, ND);
+bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *ND) {
- Call(CXCursor_ObjCPropertyDecl, ND);
+bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
- for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
- E = PID->protocol_end(); I != E; ++I)
- Call(CXCursor_ObjCProtocolRef, *I);
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ if (Visit(TL.getResultLoc()))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (Visit(MakeCXCursor(TL.getArg(I), TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ if (Visit(TL.getElementLoc()))
+ return true;
+
+ if (Expr *Size = TL.getSizeExpr())
+ return Visit(MakeCXCursor(Size, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
+}
+
+bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitStmt(Stmt *S) {
+ for (Stmt::child_iterator Child = S->child_begin(), ChildEnd = S->child_end();
+ Child != ChildEnd; ++Child) {
+ if (Visit(MakeCXCursor(*Child, StmtParent, TU)))
+ return true;
+ }
- VisitDeclContext(dyn_cast<DeclContext>(PID));
+ return false;
}
-void CDeclVisitor::VisitParmVarDecl(ParmVarDecl *ND) {
- Call(CXCursor_ParmDecl, ND);
+bool CursorVisitor::VisitDeclStmt(DeclStmt *S) {
+ for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ if (Visit(MakeCXCursor(*D, TU)))
+ return true;
+ }
+
+ return false;
}
-void CDeclVisitor::VisitTagDecl(TagDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitIfStmt(IfStmt *S) {
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ } else if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
+ return true;
+
+ if (S->getThen() && Visit(MakeCXCursor(S->getThen(), StmtParent, TU)))
+ return true;
+
+ if (S->getElse() && Visit(MakeCXCursor(S->getElse(), StmtParent, TU)))
+ return true;
+
+ return false;
}
-void CDeclVisitor::VisitVarDecl(VarDecl *ND) {
- Call(CXCursor_VarDecl, ND);
+bool CursorVisitor::VisitSwitchStmt(SwitchStmt *S) {
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ } else if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
+ return true;
+
+ if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
+ return true;
+
+ return false;
}
-static SourceLocation getLocationFromCursor(CXCursor C,
- SourceManager &SourceMgr,
- NamedDecl *ND) {
- if (clang_isReference(C.kind)) {
- switch (C.kind) {
- case CXCursor_ObjCClassRef: {
- if (isa<ObjCInterfaceDecl>(ND)) {
- // FIXME: This is a hack (storing the parent decl in the stmt slot).
- NamedDecl *parentDecl = static_cast<NamedDecl *>(C.stmt);
- return parentDecl->getLocation();
- }
- ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing category decl");
- return OID->getClassInterface()->getLocation();
- }
- case CXCursor_ObjCSuperClassRef: {
- ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing interface decl");
- return OID->getSuperClassLoc();
- }
- case CXCursor_ObjCProtocolRef: {
- ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing protocol decl");
- return OID->getLocation();
- }
- case CXCursor_ObjCSelectorRef: {
- ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(OME && "clang_getCursorLine(): Missing message expr");
- return OME->getLeftLoc(); /* FIXME: should be a range */
- }
- case CXCursor_VarRef:
- case CXCursor_FunctionRef:
- case CXCursor_EnumConstantRef: {
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
- return DRE->getLocation();
- }
- default:
- return SourceLocation();
- }
- } else { // We have a declaration or a definition.
- SourceLocation SLoc;
- switch (ND->getKind()) {
- case Decl::ObjCInterface: {
- SLoc = dyn_cast<ObjCInterfaceDecl>(ND)->getClassLoc();
- break;
- }
- case Decl::ObjCProtocol: {
- SLoc = ND->getLocation(); /* FIXME: need to get the name location. */
- break;
- }
- default: {
- SLoc = ND->getLocation();
- break;
- }
- }
- if (SLoc.isInvalid())
- return SourceLocation();
- return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
+bool CursorVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ if (E->isArgumentType()) {
+ if (TypeSourceInfo *TSInfo = E->getArgumentTypeInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
}
+
+ return VisitExpr(E);
+}
+
+bool CursorVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+ if (TypeSourceInfo *TSInfo = E->getTypeInfoAsWritten())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return VisitCastExpr(E);
+}
+
+bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ if (TypeSourceInfo *TSInfo = E->getTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return VisitExpr(E);
}
CXString CIndexer::createCXString(const char *String, bool DupString){
@@ -484,7 +871,7 @@ CXString CIndexer::createCXString(const char *String, bool DupString){
extern "C" {
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics) {
- CIndexer *CIdxr = new CIndexer(new Program());
+ CIndexer *CIdxr = new CIndexer();
if (excludeDeclarationsFromPCH)
CIdxr->setOnlyLocalDecls();
if (displayDiagnostics)
@@ -518,10 +905,22 @@ CXTranslationUnit
clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
- const char **command_line_args) {
+ const char **command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files) {
assert(CIdx && "Passed null CXIndex");
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
+ unsaved_files[I].Contents + unsaved_files[I].Length,
+ unsaved_files[I].Filename);
+ RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
+ }
+
if (!CXXIdx->getUseExternalASTGeneration()) {
llvm::SmallVector<const char *, 16> Args;
@@ -544,7 +943,9 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
CXXIdx->getDiags(),
CXXIdx->getClangResourcesPath(),
CXXIdx->getOnlyLocalDecls(),
- /* UseBumpAllocator = */ true));
+ /* UseBumpAllocator = */ true,
+ RemappedFiles.data(),
+ RemappedFiles.size()));
// FIXME: Until we have broader testing, just drop the entire AST if we
// encountered an error.
@@ -575,6 +976,17 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
char astTmpFile[L_tmpnam];
argv.push_back(tmpnam(astTmpFile));
+ // Remap any unsaved files to temporary files.
+ std::vector<llvm::sys::Path> TemporaryFiles;
+ std::vector<std::string> RemapArgs;
+ if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
+ return 0;
+
+ // The pointers into the elements of RemapArgs are stable because we
+ // won't be adding anything to RemapArgs after this point.
+ for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
+ argv.push_back(RemapArgs[i].c_str());
+
// Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
for (int i = 0; i < num_command_line_args; ++i)
if (const char *arg = command_line_args[i]) {
@@ -615,11 +1027,17 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
llvm::errs() << '\n';
}
- // Finally, we create the translation unit from the ast file.
- ASTUnit *ATU = static_cast<ASTUnit *>(
- clang_createTranslationUnit(CIdx, astTmpFile));
+ ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, CXXIdx->getDiags(),
+ CXXIdx->getOnlyLocalDecls(),
+ /* UseBumpAllocator = */ true,
+ RemappedFiles.data(),
+ RemappedFiles.size());
if (ATU)
ATU->unlinkTemporaryFile();
+
+ for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
+ TemporaryFiles[i].eraseFromDisk();
+
return ATU;
}
@@ -635,165 +1053,123 @@ CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
true);
}
-void clang_loadTranslationUnit(CXTranslationUnit CTUnit,
- CXTranslationUnitIterator callback,
- CXClientData CData) {
- assert(CTUnit && "Passed null CXTranslationUnit");
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
- ASTContext &Ctx = CXXUnit->getASTContext();
-
- unsigned PCHLevel = Decl::MaxPCHLevel;
-
- // Set the PCHLevel to filter out unwanted decls if requested.
- if (CXXUnit->getOnlyLocalDecls()) {
- PCHLevel = 0;
-
- // If the main input was an AST, bump the level.
- if (CXXUnit->isMainFileAST())
- ++PCHLevel;
- }
-
- TUVisitor DVisit(CTUnit, callback, CData, PCHLevel);
-
- // If using a non-AST based ASTUnit, iterate over the stored list of top-level
- // decls.
- if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls()) {
- const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
- for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
- ie = TLDs.end(); it != ie; ++it) {
- DVisit.Visit(*it);
- }
- } else
- DVisit.Visit(Ctx.getTranslationUnitDecl());
+CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
+ CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } };
+ return Result;
}
-void clang_loadDeclaration(CXDecl Dcl,
- CXDeclIterator callback,
- CXClientData CData) {
- assert(Dcl && "Passed null CXDecl");
-
- CDeclVisitor DVisit(Dcl, callback, CData,
- static_cast<Decl *>(Dcl)->getPCHLevel());
- DVisit.Visit(static_cast<Decl *>(Dcl));
-}
} // end: extern "C"
//===----------------------------------------------------------------------===//
-// CXDecl Operations.
+// CXSourceLocation and CXSourceRange Operations.
//===----------------------------------------------------------------------===//
-static const FileEntry *getFileEntryFromSourceLocation(SourceManager &SMgr,
- SourceLocation SLoc) {
- FileID FID;
- if (SLoc.isFileID())
- FID = SMgr.getFileID(SLoc);
- else
- FID = SMgr.getDecomposedSpellingLoc(SLoc).first;
- return SMgr.getFileEntryForID(FID);
-}
-
extern "C" {
-CXString clang_getDeclSpelling(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
-
- if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
- return CIndexer::createCXString(OMD->getSelector().getAsString().c_str(),
- true);
-
- if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
- // No, this isn't the same as the code below. getIdentifier() is non-virtual
- // and returns different names. NamedDecl returns the class name and
- // ObjCCategoryImplDecl returns the category name.
- return CIndexer::createCXString(CIMP->getIdentifier()->getNameStart());
-
- if (ND->getIdentifier())
- return CIndexer::createCXString(ND->getIdentifier()->getNameStart());
-
- return CIndexer::createCXString("");
+CXSourceLocation clang_getNullLocation() {
+ CXSourceLocation Result = { 0, 0 };
+ return Result;
}
-unsigned clang_getDeclLine(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
- return SourceMgr.getSpellingLineNumber(ND->getLocation());
+unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
+ return loc1.ptr_data == loc2.ptr_data && loc1.int_data == loc2.int_data;
}
-unsigned clang_getDeclColumn(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
- return SourceMgr.getSpellingColumnNumber(ND->getLocation());
-}
+CXSourceLocation clang_getLocation(CXTranslationUnit tu,
+ CXFile file,
+ unsigned line,
+ unsigned column) {
+ if (!tu)
+ return clang_getNullLocation();
-CXDeclExtent clang_getDeclExtent(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SM = ND->getASTContext().getSourceManager();
- SourceRange R = ND->getSourceRange();
-
- SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
- SourceLocation End = SM.getInstantiationLoc(R.getEnd());
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
+ SourceLocation SLoc
+ = CXXUnit->getSourceManager().getLocation(
+ static_cast<const FileEntry *>(file),
+ line, column);
+
+ return translateSourceLocation(CXXUnit->getASTContext(), SLoc, false);
+}
- if (!Begin.isValid()) {
- CXDeclExtent extent = { { 0, 0 }, { 0, 0 } };
- return extent;
+CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
+ if (begin.ptr_data != end.ptr_data) {
+ CXSourceRange Result = { 0, 0, 0 };
+ return Result;
}
+ CXSourceRange Result = { begin.ptr_data, begin.int_data, end.int_data };
+ return Result;
+}
+
+void clang_getInstantiationLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column) {
+ CXSourceLocationPtr Ptr
+ = CXSourceLocationPtr::getFromOpaqueValue(location.ptr_data);
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!Ptr.getPointer() || Loc.isInvalid()) {
+ if (file)
+ *file = 0;
+ if (line)
+ *line = 0;
+ if (column)
+ *column = 0;
+ return;
+ }
+
// FIXME: This is largely copy-paste from
///TextDiagnosticPrinter::HighlightRange. When it is clear that this is
- // what we want the two routines should be refactored.
-
- // If the End location and the start location are the same and are a macro
- // location, then the range was something that came from a macro expansion
- // or _Pragma. If this is an object-like macro, the best we can do is to
- // get the range. If this is a function-like macro, we'd also like to
- // get the arguments.
- if (Begin == End && R.getEnd().isMacroID())
- End = SM.getInstantiationRange(R.getEnd()).second;
-
- assert(SM.getFileID(Begin) == SM.getFileID(End));
- unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
- unsigned EndLineNo = SM.getInstantiationLineNumber(End);
-
- // Compute the column number of the start. Keep the column based at 1.
- unsigned StartColNo = SM.getInstantiationColumnNumber(Begin);
-
- // Compute the column number of the end.
- unsigned EndColNo = SM.getInstantiationColumnNumber(End);
- if (EndColNo) {
- // Offset the end column by 1 so that we point to the last character
- // in the last token.
- --EndColNo;
-
- // Add in the length of the token, so that we cover multi-char tokens.
- ASTContext &Ctx = ND->getTranslationUnitDecl()->getASTContext();
- const LangOptions &LOpts = Ctx.getLangOptions();
-
- EndColNo += Lexer::MeasureTokenLength(End, SM, LOpts);
+ // what we want the two routines should be refactored.
+ ASTContext &Context = *Ptr.getPointer();
+ SourceManager &SM = Context.getSourceManager();
+ SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
+
+ if (Ptr.getInt()) {
+ // We want the last character in this location, so we will adjust
+ // the instantiation location accordingly.
+
+ // If the location is from a macro instantiation, get the end of
+ // the instantiation range.
+ if (Loc.isMacroID())
+ InstLoc = SM.getInstantiationRange(Loc).second;
+
+ // Measure the length token we're pointing at, so we can adjust
+ // the physical location in the file to point at the last
+ // character.
+ // FIXME: This won't cope with trigraphs or escaped newlines
+ // well. For that, we actually need a preprocessor, which isn't
+ // currently available here. Eventually, we'll switch the pointer
+ // data of CXSourceLocation/CXSourceRange to a translation unit
+ // (CXXUnit), so that the preprocessor will be available here. At
+ // that point, we can use Preprocessor::getLocForEndOfToken().
+ unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM,
+ Context.getLangOptions());
+ if (Length > 0)
+ InstLoc = InstLoc.getFileLocWithOffset(Length - 1);
}
- // Package up the line/column data and return to the caller.
- CXDeclExtent extent = { { StartLineNo, StartColNo },
- { EndLineNo, EndColNo } };
- return extent;
+ if (file)
+ *file = (void *)SM.getFileEntryForID(SM.getFileID(InstLoc));
+ if (line)
+ *line = SM.getInstantiationLineNumber(InstLoc);
+ if (column)
+ *column = SM.getInstantiationColumnNumber(InstLoc);
}
-const char *clang_getDeclSource(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- FileEntry *FEnt = static_cast<FileEntry *>(clang_getDeclSourceFile(AnonDecl));
- assert(FEnt && "Cannot find FileEntry for Decl");
- return clang_getFileName(FEnt);
+CXSourceLocation clang_getRangeStart(CXSourceRange range) {
+ CXSourceLocation Result = { range.ptr_data, range.begin_int_data };
+ return Result;
}
-
-CXFile clang_getDeclSourceFile(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
- return (void *)getFileEntryFromSourceLocation(SourceMgr, ND->getLocation());
+CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
+ llvm::PointerIntPair<ASTContext *, 1, bool> Ptr;
+ Ptr.setPointer(static_cast<ASTContext *>(range.ptr_data));
+ Ptr.setInt(true);
+ CXSourceLocation Result = { Ptr.getOpaqueValue(), range.end_int_data };
+ return Result;
}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
@@ -802,58 +1178,40 @@ CXFile clang_getDeclSourceFile(CXDecl AnonDecl) {
extern "C" {
const char *clang_getFileName(CXFile SFile) {
+ if (!SFile)
+ return 0;
+
assert(SFile && "Passed null CXFile");
FileEntry *FEnt = static_cast<FileEntry *>(SFile);
return FEnt->getName();
}
time_t clang_getFileTime(CXFile SFile) {
+ if (!SFile)
+ return 0;
+
assert(SFile && "Passed null CXFile");
FileEntry *FEnt = static_cast<FileEntry *>(SFile);
return FEnt->getModificationTime();
}
+
+CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
+ if (!tu)
+ return 0;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
+
+ FileManager &FMgr = CXXUnit->getFileManager();
+ const FileEntry *File = FMgr.getFile(file_name, file_name+strlen(file_name));
+ return const_cast<FileEntry *>(File);
+}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
// CXCursor Operations.
//===----------------------------------------------------------------------===//
-static enum CXCursorKind TranslateKind(Decl *D) {
- switch (D->getKind()) {
- case Decl::Function: return CXCursor_FunctionDecl;
- case Decl::Typedef: return CXCursor_TypedefDecl;
- case Decl::Enum: return CXCursor_EnumDecl;
- case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
- case Decl::Record: return CXCursor_StructDecl; // FIXME: union/class
- case Decl::Field: return CXCursor_FieldDecl;
- case Decl::Var: return CXCursor_VarDecl;
- case Decl::ParmVar: return CXCursor_ParmDecl;
- case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
- case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
- case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
- case Decl::ObjCMethod: {
- ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
- if (MD->isInstanceMethod())
- return CXCursor_ObjCInstanceMethodDecl;
- return CXCursor_ObjCClassMethodDecl;
- }
- default: break;
- }
- return CXCursor_NotImplemented;
-}
-
-
-static CXCursor MakeCXCursor(CXCursorKind K, Decl *D) {
- CXCursor C = { K, D, 0, 0 };
- return C;
-}
-
-static CXCursor MakeCXCursor(CXCursorKind K, Decl *D, Stmt *S) {
- assert(clang_isReference(K));
- CXCursor C = { K, D, S, 0 };
- return C;
-}
-
static Decl *getDeclFromExpr(Stmt *E) {
if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
return RefExpr->getDecl();
@@ -873,53 +1231,90 @@ static Decl *getDeclFromExpr(Stmt *E) {
}
extern "C" {
+
+unsigned clang_visitChildren(CXCursor parent,
+ CXCursorVisitor visitor,
+ CXClientData client_data) {
+ ASTUnit *CXXUnit = getCursorASTUnit(parent);
+
+ unsigned PCHLevel = Decl::MaxPCHLevel;
+
+ // Set the PCHLevel to filter out unwanted decls if requested.
+ if (CXXUnit->getOnlyLocalDecls()) {
+ PCHLevel = 0;
+
+ // If the main input was an AST, bump the level.
+ if (CXXUnit->isMainFileAST())
+ ++PCHLevel;
+ }
+
+ CursorVisitor CursorVis(CXXUnit, visitor, client_data, PCHLevel);
+ return CursorVis.VisitChildren(parent);
+}
+
+static CXString getDeclSpelling(Decl *D) {
+ NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D);
+ if (!ND)
+ return CIndexer::createCXString("");
+
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ return CIndexer::createCXString(OMD->getSelector().getAsString().c_str(),
+ true);
+
+ if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
+ // No, this isn't the same as the code below. getIdentifier() is non-virtual
+ // and returns different names. NamedDecl returns the class name and
+ // ObjCCategoryImplDecl returns the category name.
+ return CIndexer::createCXString(CIMP->getIdentifier()->getNameStart());
+
+ if (ND->getIdentifier())
+ return CIndexer::createCXString(ND->getIdentifier()->getNameStart());
+
+ return CIndexer::createCXString("");
+}
+
CXString clang_getCursorSpelling(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
+ assert(getCursorDecl(C) && "CXCursor has null decl");
+ if (clang_isTranslationUnit(C.kind))
+ return clang_getTranslationUnitSpelling(C.data[2]);
if (clang_isReference(C.kind)) {
switch (C.kind) {
case CXCursor_ObjCSuperClassRef: {
- ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing interface decl");
- return CIndexer::createCXString(OID->getSuperClass()->getIdentifier()
- ->getNameStart());
+ ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
+ return CIndexer::createCXString(Super->getIdentifier()->getNameStart());
}
case CXCursor_ObjCClassRef: {
- if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND))
- return CIndexer::createCXString(OID->getIdentifier()->getNameStart());
-
- ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(ND);
- assert(OCD && "clang_getCursorLine(): Missing category decl");
- return CIndexer::createCXString(OCD->getClassInterface()->getIdentifier()
- ->getNameStart());
+ ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+ return CIndexer::createCXString(Class->getIdentifier()->getNameStart());
}
case CXCursor_ObjCProtocolRef: {
- ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing protocol decl");
+ ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
+ assert(OID && "getCursorSpelling(): Missing protocol decl");
return CIndexer::createCXString(OID->getIdentifier()->getNameStart());
}
- case CXCursor_ObjCSelectorRef: {
- ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(OME && "clang_getCursorLine(): Missing message expr");
- return CIndexer::createCXString(OME->getSelector().getAsString().c_str(),
+ case CXCursor_TypeRef: {
+ TypeDecl *Type = getCursorTypeRef(C).first;
+ assert(Type && "Missing type decl");
+
+ return CIndexer::createCXString(
+ getCursorContext(C).getTypeDeclType(Type).getAsString().c_str(),
true);
}
- case CXCursor_VarRef:
- case CXCursor_FunctionRef:
- case CXCursor_EnumConstantRef: {
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
- return CIndexer::createCXString(DRE->getDecl()->getIdentifier()
- ->getNameStart());
- }
+
default:
return CIndexer::createCXString("<not implemented>");
}
}
- return clang_getDeclSpelling(C.decl);
+
+ if (clang_isExpression(C.kind)) {
+ Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return getDeclSpelling(D);
+ return CIndexer::createCXString("");
+ }
+
+ return getDeclSpelling(getCursorDecl(C));
}
const char *clang_getCursorKindSpelling(enum CXCursorKind Kind) {
@@ -941,90 +1336,66 @@ const char *clang_getCursorKindSpelling(enum CXCursorKind Kind) {
case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
- case CXCursor_FunctionDefn: return "FunctionDefn";
- case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn";
- case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn";
- case CXCursor_ObjCClassDefn: return "ObjCClassDefn";
- case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn";
+ case CXCursor_ObjCImplementationDecl: return "ObjCImplementationDecl";
+ case CXCursor_ObjCCategoryImplDecl: return "ObjCCategoryImplDecl";
+ case CXCursor_UnexposedDecl: return "UnexposedDecl";
case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef";
case CXCursor_ObjCClassRef: return "ObjCClassRef";
- case CXCursor_ObjCSelectorRef: return "ObjCSelectorRef";
-
- case CXCursor_VarRef: return "VarRef";
- case CXCursor_FunctionRef: return "FunctionRef";
- case CXCursor_EnumConstantRef: return "EnumConstantRef";
- case CXCursor_MemberRef: return "MemberRef";
-
+ case CXCursor_TypeRef: return "TypeRef";
+ case CXCursor_UnexposedExpr: return "UnexposedExpr";
+ case CXCursor_DeclRefExpr: return "DeclRefExpr";
+ case CXCursor_MemberRefExpr: return "MemberRefExpr";
+ case CXCursor_CallExpr: return "CallExpr";
+ case CXCursor_ObjCMessageExpr: return "ObjCMessageExpr";
+ case CXCursor_UnexposedStmt: return "UnexposedStmt";
case CXCursor_InvalidFile: return "InvalidFile";
case CXCursor_NoDeclFound: return "NoDeclFound";
case CXCursor_NotImplemented: return "NotImplemented";
- default: return "<not implemented>";
+ case CXCursor_TranslationUnit: return "TranslationUnit";
}
+
+ llvm_unreachable("Unhandled CXCursorKind");
+ return NULL;
}
-CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,
- unsigned line, unsigned column) {
- assert(CTUnit && "Passed null CXTranslationUnit");
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
-
- FileManager &FMgr = CXXUnit->getFileManager();
- const FileEntry *File = FMgr.getFile(source_name,
- source_name+strlen(source_name));
- if (!File)
+enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ CXCursor *BestCursor = static_cast<CXCursor *>(client_data);
+ *BestCursor = cursor;
+ return CXChildVisit_Recurse;
+}
+
+CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
+ if (!TU)
return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
- SourceLocation SLoc =
- CXXUnit->getSourceManager().getLocation(File, line, column);
-
- ASTLocation LastLoc = CXXUnit->getLastASTLocation();
- ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc,
- &LastLoc);
-
- // FIXME: This doesn't look thread-safe.
- if (ALoc.isValid())
- CXXUnit->setLastASTLocation(ALoc);
-
- Decl *Dcl = ALoc.getParentDecl();
- if (ALoc.isNamedRef())
- Dcl = ALoc.AsNamedRef().ND;
- Stmt *Stm = ALoc.dyn_AsStmt();
- if (Dcl) {
- if (Stm) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Stm))
- return MakeCXCursor(TranslateDeclRefExpr(DRE), Dcl, Stm);
- else if (ObjCMessageExpr *MExp = dyn_cast<ObjCMessageExpr>(Stm))
- return MakeCXCursor(CXCursor_ObjCSelectorRef, Dcl, MExp);
- // Fall through...treat as a decl, not a ref.
- }
- if (ALoc.isNamedRef()) {
- if (isa<ObjCInterfaceDecl>(Dcl)) {
- CXCursor C = { CXCursor_ObjCClassRef, Dcl, ALoc.getParentDecl(), 0 };
- return C;
- }
- if (isa<ObjCProtocolDecl>(Dcl)) {
- CXCursor C = { CXCursor_ObjCProtocolRef, Dcl, ALoc.getParentDecl(), 0 };
- return C;
- }
- }
- return MakeCXCursor(TranslateKind(Dcl), Dcl);
+ SourceLocation SLoc = translateSourceLocation(Loc);
+ CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
+ if (SLoc.isValid()) {
+ SourceRange RegionOfInterest(SLoc,
+ CXXUnit->getPreprocessor().getLocForEndOfToken(SLoc, 1));
+
+ // FIXME: Would be great to have a "hint" cursor, then walk from that
+ // hint cursor upward until we find a cursor whose source range encloses
+ // the region of interest, rather than starting from the translation unit.
+ CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
+ CursorVisitor CursorVis(CXXUnit, GetCursorVisitor, &Result,
+ Decl::MaxPCHLevel, RegionOfInterest);
+ CursorVis.VisitChildren(Parent);
}
- return MakeCXCursor(CXCursor_NoDeclFound, 0);
+ return Result;
}
CXCursor clang_getNullCursor(void) {
- return MakeCXCursor(CXCursor_InvalidFile, 0);
+ return MakeCXCursorInvalid(CXCursor_InvalidFile);
}
unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
- return X.kind == Y.kind && X.decl == Y.decl && X.stmt == Y.stmt &&
- X.referringDecl == Y.referringDecl;
-}
-
-CXCursor clang_getCursorFromDecl(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- return MakeCXCursor(TranslateKind(ND), ND);
+ return X == Y;
}
unsigned clang_isInvalid(enum CXCursorKind K) {
@@ -1039,80 +1410,413 @@ unsigned clang_isReference(enum CXCursorKind K) {
return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
}
-unsigned clang_isDefinition(enum CXCursorKind K) {
- return K >= CXCursor_FirstDefn && K <= CXCursor_LastDefn;
+unsigned clang_isExpression(enum CXCursorKind K) {
+ return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
+}
+
+unsigned clang_isStatement(enum CXCursorKind K) {
+ return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
+}
+
+unsigned clang_isTranslationUnit(enum CXCursorKind K) {
+ return K == CXCursor_TranslationUnit;
}
CXCursorKind clang_getCursorKind(CXCursor C) {
return C.kind;
}
-CXDecl clang_getCursorDecl(CXCursor C) {
- if (clang_isDeclaration(C.kind))
- return C.decl;
+static SourceLocation getLocationFromExpr(Expr *E) {
+ if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
+ return /*FIXME:*/Msg->getLeftLoc();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return DRE->getLocation();
+ if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
+ return Member->getMemberLoc();
+ if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
+ return Ivar->getLocation();
+ return E->getLocStart();
+}
+CXSourceLocation clang_getCursorLocation(CXCursor C) {
if (clang_isReference(C.kind)) {
- if (C.stmt) {
- if (C.kind == CXCursor_ObjCClassRef ||
- C.kind == CXCursor_ObjCProtocolRef)
- return static_cast<Stmt *>(C.stmt);
- else
- return getDeclFromExpr(static_cast<Stmt *>(C.stmt));
- } else
- return C.decl;
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCSuperClassRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
}
- return 0;
-}
-unsigned clang_getCursorLine(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+ if (clang_isExpression(C.kind))
+ return translateSourceLocation(getCursorContext(C),
+ getLocationFromExpr(getCursorExpr(C)));
+
+ if (!getCursorDecl(C)) {
+ CXSourceLocation empty = { 0, 0 };
+ return empty;
+ }
- SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
- return SourceMgr.getSpellingLineNumber(SLoc);
+ Decl *D = getCursorDecl(C);
+ SourceLocation Loc = D->getLocation();
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
+ Loc = Class->getClassLoc();
+ return translateSourceLocation(D->getASTContext(), Loc);
}
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCSuperClassRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
+ }
+
+ if (clang_isExpression(C.kind))
+ return translateSourceRange(getCursorContext(C),
+ getCursorExpr(C)->getSourceRange());
+
+ if (clang_isStatement(C.kind))
+ return translateSourceRange(getCursorContext(C),
+ getCursorStmt(C)->getSourceRange());
-unsigned clang_getCursorColumn(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+ if (!getCursorDecl(C)) {
+ CXSourceRange empty = { 0, 0, 0 };
+ return empty;
+ }
- SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
- return SourceMgr.getSpellingColumnNumber(SLoc);
+ Decl *D = getCursorDecl(C);
+ return translateSourceRange(D->getASTContext(), D->getSourceRange());
}
-const char *clang_getCursorSource(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+CXCursor clang_getCursorReferenced(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
- SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
+ ASTUnit *CXXUnit = getCursorASTUnit(C);
+ if (clang_isDeclaration(C.kind))
+ return C;
- if (SLoc.isFileID()) {
- const char *bufferName = SourceMgr.getBufferName(SLoc);
- return bufferName[0] == '<' ? NULL : bufferName;
+ if (clang_isExpression(C.kind)) {
+ Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return MakeCXCursor(D, CXXUnit);
+ return clang_getNullCursor();
}
+
+ if (!clang_isReference(C.kind))
+ return clang_getNullCursor();
- // Retrieve the file in which the macro was instantiated, then provide that
- // buffer name.
- // FIXME: Do we want to give specific macro-instantiation information?
- const llvm::MemoryBuffer *Buffer
- = SourceMgr.getBuffer(SourceMgr.getDecomposedSpellingLoc(SLoc).first);
- if (!Buffer)
- return 0;
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef:
+ return MakeCXCursor(getCursorObjCSuperClassRef(C).first, CXXUnit);
+
+ case CXCursor_ObjCProtocolRef: {
+ return MakeCXCursor(getCursorObjCProtocolRef(C).first, CXXUnit);
+
+ case CXCursor_ObjCClassRef:
+ return MakeCXCursor(getCursorObjCClassRef(C).first, CXXUnit);
+
+ case CXCursor_TypeRef:
+ return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
+
+ default:
+ // We would prefer to enumerate all non-reference cursor kinds here.
+ llvm_unreachable("Unhandled reference cursor kind");
+ break;
+ }
+ }
- return Buffer->getBufferIdentifier();
+ return clang_getNullCursor();
}
-CXFile clang_getCursorSourceFile(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+CXCursor clang_getCursorDefinition(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = getCursorASTUnit(C);
+
+ bool WasReference = false;
+ if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
+ C = clang_getCursorReferenced(C);
+ WasReference = true;
+ }
+
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullCursor();
+
+ Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+
+ switch (D->getKind()) {
+ // Declaration kinds that don't really separate the notions of
+ // declaration and definition.
+ case Decl::Namespace:
+ case Decl::Typedef:
+ case Decl::TemplateTypeParm:
+ case Decl::EnumConstant:
+ case Decl::Field:
+ case Decl::ObjCIvar:
+ case Decl::ObjCAtDefsField:
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ case Decl::NonTypeTemplateParm:
+ case Decl::TemplateTemplateParm:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::LinkageSpec:
+ case Decl::ObjCPropertyImpl:
+ case Decl::FileScopeAsm:
+ case Decl::StaticAssert:
+ case Decl::Block:
+ return C;
+
+ // Declaration kinds that don't make any sense here, but are
+ // nonetheless harmless.
+ case Decl::TranslationUnit:
+ case Decl::Template:
+ case Decl::ObjCContainer:
+ break;
+
+ // Declaration kinds for which the definition is not resolvable.
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ break;
+
+ case Decl::UsingDirective:
+ return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
+ CXXUnit);
+
+ case Decl::NamespaceAlias:
+ return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), CXXUnit);
+
+ case Decl::Enum:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::ClassTemplatePartialSpecialization:
+ if (TagDecl *Def = cast<TagDecl>(D)->getDefinition(D->getASTContext()))
+ return MakeCXCursor(Def, CXXUnit);
+ return clang_getNullCursor();
+
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion: {
+ const FunctionDecl *Def = 0;
+ if (cast<FunctionDecl>(D)->getBody(Def))
+ return MakeCXCursor(const_cast<FunctionDecl *>(Def), CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Var: {
+ VarDecl *Var = cast<VarDecl>(D);
+
+ // Variables with initializers have definitions.
+ const VarDecl *Def = 0;
+ if (Var->getDefinition(Def))
+ return MakeCXCursor(const_cast<VarDecl *>(Def), CXXUnit);
+
+ // extern and private_extern variables are not definitions.
+ if (Var->hasExternalStorage())
+ return clang_getNullCursor();
+
+ // In-line static data members do not have definitions.
+ if (Var->isStaticDataMember() && !Var->isOutOfLine())
+ return clang_getNullCursor();
+
+ // All other variables are themselves definitions.
+ return C;
+ }
+
+ case Decl::FunctionTemplate: {
+ const FunctionDecl *Def = 0;
+ if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
+ return MakeCXCursor(Def->getDescribedFunctionTemplate(), CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ case Decl::ClassTemplate: {
+ if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
+ ->getDefinition(D->getASTContext()))
+ return MakeCXCursor(
+ cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
+ CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Using: {
+ UsingDecl *Using = cast<UsingDecl>(D);
+ CXCursor Def = clang_getNullCursor();
+ for (UsingDecl::shadow_iterator S = Using->shadow_begin(),
+ SEnd = Using->shadow_end();
+ S != SEnd; ++S) {
+ if (Def != clang_getNullCursor()) {
+ // FIXME: We have no way to return multiple results.
+ return clang_getNullCursor();
+ }
+
+ Def = clang_getCursorDefinition(MakeCXCursor((*S)->getTargetDecl(),
+ CXXUnit));
+ }
+
+ return Def;
+ }
+
+ case Decl::UsingShadow:
+ return clang_getCursorDefinition(
+ MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),
+ CXXUnit));
+
+ case Decl::ObjCMethod: {
+ ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
+ if (Method->isThisDeclarationADefinition())
+ return C;
+
+ // Dig out the method definition in the associated
+ // @implementation, if we have it.
+ // FIXME: The ASTs should make finding the definition easier.
+ if (ObjCInterfaceDecl *Class
+ = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
+ if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
+ if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ if (Def->isThisDeclarationADefinition())
+ return MakeCXCursor(Def, CXXUnit);
+
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCCategory:
+ if (ObjCCategoryImplDecl *Impl
+ = cast<ObjCCategoryDecl>(D)->getImplementation())
+ return MakeCXCursor(Impl, CXXUnit);
+ return clang_getNullCursor();
+
+ case Decl::ObjCProtocol:
+ if (!cast<ObjCProtocolDecl>(D)->isForwardDecl())
+ return C;
+ return clang_getNullCursor();
+
+ case Decl::ObjCInterface:
+ // There are two notions of a "definition" for an Objective-C
+ // class: the interface and its implementation. When we resolved a
+ // reference to an Objective-C class, produce the @interface as
+ // the definition; when we were provided with the interface,
+ // produce the @implementation as the definition.
+ if (WasReference) {
+ if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
+ return C;
+ } else if (ObjCImplementationDecl *Impl
+ = cast<ObjCInterfaceDecl>(D)->getImplementation())
+ return MakeCXCursor(Impl, CXXUnit);
+ return clang_getNullCursor();
- return (void *)
- getFileEntryFromSourceLocation(SourceMgr, getLocationFromCursor(C,SourceMgr,
- ND));
+ case Decl::ObjCProperty:
+ // FIXME: We don't really know where to find the
+ // ObjCPropertyImplDecls that implement this property.
+ return clang_getNullCursor();
+
+ case Decl::ObjCCompatibleAlias:
+ if (ObjCInterfaceDecl *Class
+ = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
+ if (!Class->isForwardDecl())
+ return MakeCXCursor(Class, CXXUnit);
+
+ return clang_getNullCursor();
+
+ case Decl::ObjCForwardProtocol: {
+ ObjCForwardProtocolDecl *Forward = cast<ObjCForwardProtocolDecl>(D);
+ if (Forward->protocol_size() == 1)
+ return clang_getCursorDefinition(
+ MakeCXCursor(*Forward->protocol_begin(),
+ CXXUnit));
+
+ // FIXME: Cannot return multiple definitions.
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCClass: {
+ ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
+ if (Class->size() == 1) {
+ ObjCInterfaceDecl *IFace = Class->begin()->getInterface();
+ if (!IFace->isForwardDecl())
+ return MakeCXCursor(IFace, CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ // FIXME: Cannot return multiple definitions.
+ return clang_getNullCursor();
+ }
+
+ case Decl::Friend:
+ if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, CXXUnit));
+ return clang_getNullCursor();
+
+ case Decl::FriendTemplate:
+ if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, CXXUnit));
+ return clang_getNullCursor();
+ }
+
+ return clang_getNullCursor();
+}
+
+unsigned clang_isCursorDefinition(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ return clang_getCursorDefinition(C) == C;
}
void clang_getDefinitionSpellingAndExtent(CXCursor C,
@@ -1122,8 +1826,8 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C,
unsigned *startColumn,
unsigned *endLine,
unsigned *endColumn) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
+ assert(getCursorDecl(C) && "CXCursor has null decl");
+ NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));
FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
@@ -1151,4 +1855,18 @@ void clang_disposeString(CXString string) {
if (string.MustFreeString && string.Spelling)
free((void*)string.Spelling);
}
+
} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Misc. utility functions.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+
+const char *clang_getClangVersion() {
+ return getClangFullVersion();
+}
+
+} // end: extern "C"
+
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index a695ba2b08d1..d349086b9c11 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -7,40 +7,41 @@ _clang_disposeIndex
_clang_disposeString
_clang_disposeTranslationUnit
_clang_equalCursors
+_clang_equalLocations
+_clang_getClangVersion
_clang_getCString
_clang_getCompletionChunkCompletionString
_clang_getCompletionChunkKind
_clang_getCompletionChunkText
_clang_getCursor
-_clang_getCursorColumn
-_clang_getCursorDecl
-_clang_getCursorFromDecl
+_clang_getCursorDefinition
+_clang_getCursorExtent
_clang_getCursorKind
_clang_getCursorKindSpelling
-_clang_getCursorLine
-_clang_getCursorSource
-_clang_getCursorSourceFile
+_clang_getCursorLocation
+_clang_getCursorReferenced
_clang_getCursorSpelling
-_clang_getDeclColumn
-_clang_getDeclExtent
-_clang_getDeclLine
-_clang_getDeclExtent
-_clang_getDeclSource
-_clang_getDeclSourceFile
-_clang_getDeclSpelling
-_clang_getDeclUSR
-_clang_getDeclaration
+_clang_getCursorUSR
_clang_getDefinitionSpellingAndExtent
-_clang_getEntityFromDecl
+_clang_getFile
_clang_getFileName
_clang_getFileTime
+_clang_getInstantiationLocation
+_clang_getLocation
_clang_getNullCursor
+_clang_getNullLocation
_clang_getNumCompletionChunks
+_clang_getRange
+_clang_getRangeEnd
+_clang_getRangeStart
+_clang_getTranslationUnitCursor
_clang_getTranslationUnitSpelling
+_clang_isCursorDefinition
_clang_isDeclaration
-_clang_isDefinition
+_clang_isExpression
_clang_isInvalid
_clang_isReference
-_clang_loadDeclaration
-_clang_loadTranslationUnit
+_clang_isStatement
+_clang_isTranslationUnit
_clang_setUseExternalASTGeneration
+_clang_visitChildren
diff --git a/tools/CIndex/CIndexCodeCompletion.cpp b/tools/CIndex/CIndexCodeCompletion.cpp
index f70479b5e8d3..f3b60dc8b01a 100644
--- a/tools/CIndex/CIndexCodeCompletion.cpp
+++ b/tools/CIndex/CIndexCodeCompletion.cpp
@@ -221,35 +221,10 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
argv.push_back("-Xclang");
argv.push_back("-code-completion-macros");
+ // Remap any unsaved files to temporary files.
std::vector<std::string> RemapArgs;
- for (unsigned i = 0; i != num_unsaved_files; ++i) {
- char tmpFile[L_tmpnam];
- char *tmpFileName = tmpnam(tmpFile);
-
- // Write the contents of this unsaved file into the temporary file.
- llvm::sys::Path SavedFile(tmpFileName);
- std::string ErrorInfo;
- llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
- if (!ErrorInfo.empty())
- continue;
-
- OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
- OS.close();
- if (OS.has_error()) {
- SavedFile.eraseFromDisk();
- continue;
- }
-
- // Remap the file.
- std::string RemapArg = unsaved_files[i].Filename;
- RemapArg += ';';
- RemapArg += tmpFileName;
- RemapArgs.push_back("-Xclang");
- RemapArgs.push_back("-remap-file");
- RemapArgs.push_back("-Xclang");
- RemapArgs.push_back(RemapArg);
- TemporaryFiles.push_back(SavedFile);
- }
+ if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
+ return 0;
// The pointers into the elements of RemapArgs are stable because we
// won't be adding anything to RemapArgs after this point.
diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp
index 549c65058d86..fd605fb68d1b 100644
--- a/tools/CIndex/CIndexUSRs.cpp
+++ b/tools/CIndex/CIndexUSRs.cpp
@@ -12,56 +12,11 @@
//===----------------------------------------------------------------------===//
#include "CIndexer.h"
+#include "CXCursor.h"
#include "clang/AST/DeclVisitor.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
-// Some notes on CXEntity:
-//
-// - Since the 'ordinary' namespace includes functions, data, typedefs,
-// ObjC interfaces, thecurrent algorithm is a bit naive (resulting in one
-// entity for 2 different types). For example:
-//
-// module1.m: @interface Foo @end Foo *x;
-// module2.m: void Foo(int);
-//
-// - Since the unique name spans translation units, static data/functions
-// within a CXTranslationUnit are *not* currently represented by entities.
-// As a result, there will be no entity for the following:
-//
-// module.m: static void Foo() { }
-//
-
-static inline Entity GetEntity(const CXEntity &E) {
- return Entity::getFromOpaquePtr(E.data);
-}
-
-static inline ASTUnit *GetTranslationUnit(CXTranslationUnit TU) {
- return (ASTUnit*) TU;
-}
-
-static inline ASTContext &GetASTContext(CXTranslationUnit TU) {
- return GetTranslationUnit(TU)->getASTContext();
-}
-
-static inline CXEntity NullCXEntity() {
- CXEntity CE;
- CE.index = NULL;
- CE.data = NULL;
- return CE;
-}
-
-static inline CXEntity MakeEntity(CXIndex CIdx, const Entity &E) {
- CXEntity CE;
- CE.index = CIdx;
- CE.data = E.getAsOpaquePtr();
- return CE;
-}
-
-static inline Program &GetProgram(CXIndex CIdx) {
- return ((CIndexer*) CIdx)->getProgram();
-}
-
//===----------------------------------------------------------------------===//
// USR generation.
//===----------------------------------------------------------------------===//
@@ -69,18 +24,22 @@ static inline Program &GetProgram(CXIndex CIdx) {
namespace {
class USRGenerator : public DeclVisitor<USRGenerator> {
llvm::raw_ostream &Out;
+ bool IgnoreResults;
public:
- USRGenerator(llvm::raw_ostream &out) : Out(out) {}
+ USRGenerator(llvm::raw_ostream &out) : Out(out), IgnoreResults(false) {}
+
+ bool ignoreResults() const { return IgnoreResults; }
void VisitBlockDecl(BlockDecl *D);
void VisitDeclContext(DeclContext *D);
+ void VisitFieldDecl(FieldDecl *D);
void VisitFunctionDecl(FunctionDecl *D);
void VisitNamedDecl(NamedDecl *D);
void VisitNamespaceDecl(NamespaceDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *CD);
void VisitObjCMethodDecl(ObjCMethodDecl *MD);
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
- void VisitRecordDecl(RecordDecl *D);
+ void VisitTagDecl(TagDecl *D);
void VisitTypedefDecl(TypedefDecl *D);
};
} // end anonymous namespace
@@ -96,6 +55,17 @@ void USRGenerator::VisitDeclContext(DeclContext *DC) {
Visit(D);
}
+void USRGenerator::VisitFieldDecl(FieldDecl *D) {
+ const std::string &s = D->getNameAsString();
+ if (s.empty()) {
+ // Bit fields can be anonymous.
+ IgnoreResults = true;
+ return;
+ }
+ VisitDeclContext(D->getDeclContext());
+ Out << "@^FI^" << s;
+}
+
void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
VisitDeclContext(D->getDeclContext());
Out << "@F^" << D->getNameAsString();
@@ -113,17 +83,6 @@ void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
Out << "@N^" << D->getNameAsString();
}
-void USRGenerator::VisitRecordDecl(RecordDecl *D) {
- VisitDeclContext(D->getDeclContext());
- Out << "@S^";
- // FIXME: Better support for anonymous structures.
- const std::string &s = D->getNameAsString();
- if (s.empty())
- Out << "^anon";
- else
- Out << s;
-}
-
void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Visit(cast<Decl>(D->getDeclContext()));
Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
@@ -141,13 +100,13 @@ void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
case Decl::ObjCCategory: {
ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
Out << "objc(cy)" << CD->getClassInterface()->getName()
- << '_' << CD->getName();
+ << '^' << CD->getName();
break;
}
case Decl::ObjCCategoryImpl: {
ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
Out << "objc(cy)" << CD->getClassInterface()->getName()
- << '_' << CD->getName();
+ << '^' << CD->getName();
break;
}
case Decl::ObjCProtocol:
@@ -161,6 +120,27 @@ void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
Out << "(py)" << D->getName();
}
+void USRGenerator::VisitTagDecl(TagDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ switch (D->getTagKind()) {
+ case TagDecl::TK_struct: Out << "@S^"; break;
+ case TagDecl::TK_class: Out << "@C^"; break;
+ case TagDecl::TK_union: Out << "@U^"; break;
+ case TagDecl::TK_enum: Out << "@E^"; break;
+ }
+
+ // FIXME: Better support for anonymous structures and enums.
+ const std::string &s = D->getNameAsString();
+ if (s.empty()) {
+ if (TypedefDecl *TD = D->getTypedefForAnonDecl())
+ Out << "^anontd^" << TD->getNameAsString();
+ else
+ Out << "^anon";
+ }
+ else
+ Out << s;
+}
+
void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
DeclContext *DC = D->getDeclContext();
if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
@@ -168,36 +148,32 @@ void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
Out << "typedef@" << D->getName();
}
-extern "C" {
-
-/// clang_getDeclaration() maps from a CXEntity to the matching CXDecl (if any)
-/// in a specified translation unit.
-CXDecl clang_getDeclaration(CXEntity CE, CXTranslationUnit TU) {
- return (CXDecl) GetEntity(CE).getDecl(GetASTContext(TU));
-}
-
-
-CXEntity clang_getEntityFromDecl(CXIndex CIdx, CXDecl CE) {
- if (Decl *D = (Decl *) CE)
- return MakeEntity(CIdx, Entity::get(D, GetProgram(CIdx)));
- return NullCXEntity();
-}
-
// FIXME: This is a skeleton implementation. It will be overhauled.
-CXString clang_getDeclUSR(CXDecl D) {
- assert(D && "Null CXDecl passed to clang_getDeclUSR()");
+static CXString ConstructUSR(Decl *D) {
llvm::SmallString<1024> StrBuf;
{
llvm::raw_svector_ostream Out(StrBuf);
USRGenerator UG(Out);
UG.Visit(static_cast<Decl*>(D));
+ if (UG.ignoreResults())
+ return CIndexer::createCXString(NULL);
}
if (StrBuf.empty())
return CIndexer::createCXString(NULL);
-
+
// Return a copy of the string that must be disposed by the caller.
return CIndexer::createCXString(StrBuf.c_str(), true);
}
+
+extern "C" {
+
+CXString clang_getCursorUSR(CXCursor C) {
+ if (Decl *D = cxcursor::getCursorDecl(C))
+ return ConstructUSR(D);
+
+ return CIndexer::createCXString(NULL);
+}
+
} // end extern "C"
diff --git a/tools/CIndex/CIndexer.cpp b/tools/CIndex/CIndexer.cpp
index f26c8ce8136b..53636a4ff351 100644
--- a/tools/CIndex/CIndexer.cpp
+++ b/tools/CIndex/CIndexer.cpp
@@ -94,3 +94,40 @@ std::string CIndexer::getClangResourcesPath() {
return P.str();
}
+
+bool clang::RemapFiles(unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ std::vector<std::string> &RemapArgs,
+ std::vector<llvm::sys::Path> &TemporaryFiles) {
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ char tmpFile[L_tmpnam];
+ char *tmpFileName = tmpnam(tmpFile);
+
+ // Write the contents of this unsaved file into the temporary file.
+ llvm::sys::Path SavedFile(tmpFileName);
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
+ if (!ErrorInfo.empty())
+ return true;
+
+ OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
+ OS.close();
+ if (OS.has_error()) {
+ SavedFile.eraseFromDisk();
+ return true;
+ }
+
+ // Remap the file.
+ std::string RemapArg = unsaved_files[i].Filename;
+ RemapArg += ';';
+ RemapArg += tmpFileName;
+ RemapArgs.push_back("-Xclang");
+ RemapArgs.push_back("-remap-file");
+ RemapArgs.push_back("-Xclang");
+ RemapArgs.push_back(RemapArg);
+ TemporaryFiles.push_back(SavedFile);
+ }
+
+ return false;
+}
+
diff --git a/tools/CIndex/CIndexer.h b/tools/CIndex/CIndexer.h
index 4f3cd8b85f71..d01454f9dc64 100644
--- a/tools/CIndex/CIndexer.h
+++ b/tools/CIndex/CIndexer.h
@@ -16,13 +16,10 @@
#define LLVM_CLANG_CINDEXER_H
#include "clang-c/Index.h"
-#include "clang/Index/ASTLocation.h"
-#include "clang/Index/Indexer.h"
-#include "clang/Index/Program.h"
-#include "clang/Index/Utils.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/ASTUnit.h"
#include "llvm/System/Path.h"
+#include <vector>
using namespace clang;
@@ -34,7 +31,7 @@ public:
virtual void HandleDiagnostic(Diagnostic::Level, const DiagnosticInfo &) {}
};
-class CIndexer : public Indexer {
+class CIndexer {
DiagnosticOptions DiagOpts;
IgnoreDiagnosticsClient IgnoreDiagClient;
llvm::OwningPtr<Diagnostic> TextDiags;
@@ -46,16 +43,12 @@ class CIndexer : public Indexer {
llvm::sys::Path ClangPath;
public:
- explicit CIndexer(Program *prog) : Indexer(*prog),
- IgnoreDiags(&IgnoreDiagClient),
- UseExternalASTGeneration(false),
- OnlyLocalDecls(false),
- DisplayDiagnostics(false) {
+ CIndexer() : IgnoreDiags(&IgnoreDiagClient), UseExternalASTGeneration(false),
+ OnlyLocalDecls(false), DisplayDiagnostics(false)
+ {
TextDiags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0));
}
- virtual ~CIndexer() { delete &getProgram(); }
-
/// \brief Whether we only want to see "local" declarations (that did not
/// come from a previous precompiled header). If false, we want to see all
/// declarations.
@@ -85,4 +78,17 @@ public:
static CXString createCXString(const char *String, bool DupString = false);
};
+namespace clang {
+ /**
+ * \brief Given a set of "unsaved" files, create temporary files and
+ * construct the clang -cc1 argument list needed to perform the remapping.
+ *
+ * \returns true if an error occurred.
+ */
+ bool RemapFiles(unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ std::vector<std::string> &RemapArgs,
+ std::vector<llvm::sys::Path> &TemporaryFiles);
+}
+
#endif
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index 52f847ef17da..730eaafb5a2e 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -3,8 +3,7 @@ set(SHARED_LIBRARY TRUE)
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
- clangIndex
- clangFrontend
+ clangFrontend
clangDriver
clangSema
clangAnalysis
@@ -24,6 +23,7 @@ add_clang_library(CIndex
CIndexCodeCompletion.cpp
CIndexUSRs.cpp
CIndexer.cpp
+ CXCursor.cpp
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
diff --git a/tools/CIndex/CXCursor.cpp b/tools/CIndex/CXCursor.cpp
new file mode 100644
index 000000000000..63d9bc9f2e9a
--- /dev/null
+++ b/tools/CIndex/CXCursor.cpp
@@ -0,0 +1,305 @@
+//===- CXCursor.cpp - Routines for manipulating CXCursors -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors. It should be the
+// only file that has internal knowledge of the encoding of the data in
+// CXCursor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXCursor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) {
+ assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid);
+ CXCursor C = { K, { 0, 0, 0 } };
+ return C;
+}
+
+static CXCursorKind GetCursorKind(Decl *D) {
+ switch (D->getKind()) {
+ case Decl::Enum: return CXCursor_EnumDecl;
+ case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
+ case Decl::Field: return CXCursor_FieldDecl;
+ case Decl::Function:
+ return CXCursor_FunctionDecl;
+ case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
+ case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
+ case Decl::ObjCClass:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCForwardProtocol:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
+ case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
+ case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
+ case Decl::ObjCMethod:
+ return cast<ObjCMethodDecl>(D)->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
+ case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
+ case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
+ case Decl::ParmVar: return CXCursor_ParmDecl;
+ case Decl::Typedef: return CXCursor_TypedefDecl;
+ case Decl::Var: return CXCursor_VarDecl;
+ default:
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ switch (TD->getTagKind()) {
+ case TagDecl::TK_struct: return CXCursor_StructDecl;
+ case TagDecl::TK_class: return CXCursor_ClassDecl;
+ case TagDecl::TK_union: return CXCursor_UnionDecl;
+ case TagDecl::TK_enum: return CXCursor_EnumDecl;
+ }
+ }
+
+ return CXCursor_UnexposedDecl;
+ }
+
+ llvm_unreachable("Invalid Decl");
+ return CXCursor_NotImplemented;
+}
+
+CXCursor cxcursor::MakeCXCursor(Decl *D, ASTUnit *TU) {
+ CXCursor C = { GetCursorKind(D), { D, 0, TU } };
+ return C;
+}
+
+CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, ASTUnit *TU) {
+ CXCursorKind K = CXCursor_NotImplemented;
+
+ switch (S->getStmtClass()) {
+ case Stmt::NoStmtClass:
+ break;
+
+ case Stmt::NullStmtClass:
+ case Stmt::CompoundStmtClass:
+ case Stmt::CaseStmtClass:
+ case Stmt::DefaultStmtClass:
+ case Stmt::LabelStmtClass:
+ case Stmt::IfStmtClass:
+ case Stmt::SwitchStmtClass:
+ case Stmt::WhileStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::ForStmtClass:
+ case Stmt::GotoStmtClass:
+ case Stmt::IndirectGotoStmtClass:
+ case Stmt::ContinueStmtClass:
+ case Stmt::BreakStmtClass:
+ case Stmt::ReturnStmtClass:
+ case Stmt::DeclStmtClass:
+ case Stmt::SwitchCaseClass:
+ case Stmt::AsmStmtClass:
+ case Stmt::ObjCAtTryStmtClass:
+ case Stmt::ObjCAtCatchStmtClass:
+ case Stmt::ObjCAtFinallyStmtClass:
+ case Stmt::ObjCAtThrowStmtClass:
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ case Stmt::ObjCForCollectionStmtClass:
+ case Stmt::CXXCatchStmtClass:
+ case Stmt::CXXTryStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+
+ case Stmt::ExprClass:
+ case Stmt::PredefinedExprClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::ParenExprClass:
+ case Stmt::UnaryOperatorClass:
+ case Stmt::SizeOfAlignOfExprClass:
+ case Stmt::ArraySubscriptExprClass:
+ case Stmt::CastExprClass:
+ case Stmt::BinaryOperatorClass:
+ case Stmt::CompoundAssignOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::ExplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ case Stmt::CompoundLiteralExprClass:
+ case Stmt::ExtVectorElementExprClass:
+ case Stmt::InitListExprClass:
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::ImplicitValueInitExprClass:
+ case Stmt::ParenListExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::AddrLabelExprClass:
+ case Stmt::StmtExprClass:
+ case Stmt::TypesCompatibleExprClass:
+ case Stmt::ChooseExprClass:
+ case Stmt::GNUNullExprClass:
+ case Stmt::CXXNamedCastExprClass:
+ case Stmt::CXXStaticCastExprClass:
+ case Stmt::CXXDynamicCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass:
+ case Stmt::CXXTypeidExprClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::CXXThisExprClass:
+ case Stmt::CXXThrowExprClass:
+ case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXZeroInitValueExprClass:
+ case Stmt::CXXNewExprClass:
+ case Stmt::CXXDeleteExprClass:
+ case Stmt::CXXPseudoDestructorExprClass:
+ case Stmt::UnresolvedLookupExprClass:
+ case Stmt::UnaryTypeTraitExprClass:
+ case Stmt::DependentScopeDeclRefExprClass:
+ case Stmt::CXXBindTemporaryExprClass:
+ case Stmt::CXXExprWithTemporariesClass:
+ case Stmt::CXXUnresolvedConstructExprClass:
+ case Stmt::CXXDependentScopeMemberExprClass:
+ case Stmt::UnresolvedMemberExprClass:
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::ObjCEncodeExprClass:
+ case Stmt::ObjCSelectorExprClass:
+ case Stmt::ObjCProtocolExprClass:
+ case Stmt::ObjCImplicitSetterGetterRefExprClass:
+ case Stmt::ObjCSuperExprClass:
+ case Stmt::ObjCIsaExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ case Stmt::BlockExprClass:
+ K = CXCursor_UnexposedExpr;
+ break;
+ case Stmt::DeclRefExprClass:
+ case Stmt::BlockDeclRefExprClass:
+ // FIXME: UnresolvedLookupExpr?
+ // FIXME: DependentScopeDeclRefExpr?
+ K = CXCursor_DeclRefExpr;
+ break;
+
+ case Stmt::MemberExprClass:
+ case Stmt::ObjCIvarRefExprClass:
+ case Stmt::ObjCPropertyRefExprClass:
+ // FIXME: UnresolvedMemberExpr?
+ // FIXME: CXXDependentScopeMemberExpr?
+ K = CXCursor_MemberRefExpr;
+ break;
+
+ case Stmt::CallExprClass:
+ case Stmt::CXXOperatorCallExprClass:
+ case Stmt::CXXMemberCallExprClass:
+ case Stmt::CXXConstructExprClass:
+ case Stmt::CXXTemporaryObjectExprClass:
+ // FIXME: CXXUnresolvedConstructExpr
+ // FIXME: ObjCImplicitSetterGetterRefExpr?
+ K = CXCursor_CallExpr;
+ break;
+
+ case Stmt::ObjCMessageExprClass:
+ K = CXCursor_ObjCMessageExpr;
+ break;
+ }
+
+ CXCursor C = { K, { Parent, S, TU } };
+ return C;
+}
+
+CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
+ SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_ObjCSuperClassRef, { Super, RawLoc, TU } };
+ return C;
+}
+
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+cxcursor::getCursorObjCSuperClassRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCSuperClassRef);
+ return std::make_pair(static_cast<ObjCInterfaceDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorObjCProtocolRef(ObjCProtocolDecl *Super,
+ SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_ObjCProtocolRef, { Super, RawLoc, TU } };
+ return C;
+}
+
+std::pair<ObjCProtocolDecl *, SourceLocation>
+cxcursor::getCursorObjCProtocolRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCProtocolRef);
+ return std::make_pair(static_cast<ObjCProtocolDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class,
+ SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, TU } };
+ return C;
+}
+
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+cxcursor::getCursorObjCClassRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCClassRef);
+ return std::make_pair(static_cast<ObjCInterfaceDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_TypeRef, { Type, RawLoc, TU } };
+ return C;
+}
+
+std::pair<TypeDecl *, SourceLocation>
+cxcursor::getCursorTypeRef(CXCursor C) {
+ assert(C.kind == CXCursor_TypeRef);
+ return std::make_pair(static_cast<TypeDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+Decl *cxcursor::getCursorDecl(CXCursor Cursor) {
+ return (Decl *)Cursor.data[0];
+}
+
+Expr *cxcursor::getCursorExpr(CXCursor Cursor) {
+ return dyn_cast_or_null<Expr>(getCursorStmt(Cursor));
+}
+
+Stmt *cxcursor::getCursorStmt(CXCursor Cursor) {
+ if (Cursor.kind == CXCursor_ObjCSuperClassRef ||
+ Cursor.kind == CXCursor_ObjCProtocolRef ||
+ Cursor.kind == CXCursor_ObjCClassRef)
+ return 0;
+
+ return (Stmt *)Cursor.data[1];
+}
+
+ASTContext &cxcursor::getCursorContext(CXCursor Cursor) {
+ return getCursorASTUnit(Cursor)->getASTContext();
+}
+
+ASTUnit *cxcursor::getCursorASTUnit(CXCursor Cursor) {
+ return static_cast<ASTUnit *>(Cursor.data[2]);
+}
+
+bool cxcursor::operator==(CXCursor X, CXCursor Y) {
+ return X.kind == Y.kind && X.data[0] == Y.data[0] && X.data[1] == Y.data[1] &&
+ X.data[2] == Y.data[2];
+}
diff --git a/tools/CIndex/CXCursor.h b/tools/CIndex/CXCursor.h
new file mode 100644
index 000000000000..546dd7f48543
--- /dev/null
+++ b/tools/CIndex/CXCursor.h
@@ -0,0 +1,88 @@
+//===- CXCursor.h - Routines for manipulating CXCursors -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CXCURSOR_H
+#define LLVM_CLANG_CXCursor_H
+
+#include "clang-c/Index.h"
+#include "clang/Basic/SourceLocation.h"
+#include <utility>
+
+namespace clang {
+
+class ASTContext;
+class ASTUnit;
+class Decl;
+class Expr;
+class NamedDecl;
+class ObjCInterfaceDecl;
+class ObjCProtocolDecl;
+class Stmt;
+class TypeDecl;
+
+namespace cxcursor {
+
+CXCursor MakeCXCursorInvalid(CXCursorKind K);
+CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent, ASTUnit *TU);
+CXCursor MakeCXCursor(clang::Decl *D, ASTUnit *TU);
+
+/// \brief Create an Objective-C superclass reference at the given location.
+CXCursor MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
+ SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack an ObjCSuperClassRef cursor into the interface it references
+/// and optionally the location where the reference occurred.
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+ getCursorObjCSuperClassRef(CXCursor C);
+
+/// \brief Create an Objective-C protocol reference at the given location.
+CXCursor MakeCursorObjCProtocolRef(ObjCProtocolDecl *Proto, SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack an ObjCProtocolRef cursor into the protocol it references
+/// and optionally the location where the reference occurred.
+std::pair<ObjCProtocolDecl *, SourceLocation>
+ getCursorObjCProtocolRef(CXCursor C);
+
+/// \brief Create an Objective-C class reference at the given location.
+CXCursor MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack an ObjCClassRef cursor into the class it references
+/// and optionally the location where the reference occurred.
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+ getCursorObjCClassRef(CXCursor C);
+
+/// \brief Create a type reference at the given location.
+CXCursor MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc, ASTUnit *TU);
+
+/// \brief Unpack a TypeRef cursor into the class it references
+/// and optionally the location where the reference occurred.
+std::pair<TypeDecl *, SourceLocation> getCursorTypeRef(CXCursor C);
+
+Decl *getCursorDecl(CXCursor Cursor);
+Expr *getCursorExpr(CXCursor Cursor);
+Stmt *getCursorStmt(CXCursor Cursor);
+ASTContext &getCursorContext(CXCursor Cursor);
+ASTUnit *getCursorASTUnit(CXCursor Cursor);
+
+bool operator==(CXCursor X, CXCursor Y);
+
+inline bool operator!=(CXCursor X, CXCursor Y) {
+ return !(X == Y);
+}
+
+}} // end namespace: clang::cxcursor
+
+#endif
diff --git a/tools/CIndex/Makefile b/tools/CIndex/Makefile
index 94f04670000d..7bdbba172f2c 100644
--- a/tools/CIndex/Makefile
+++ b/tools/CIndex/Makefile
@@ -22,7 +22,7 @@ LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
LINK_COMPONENTS := bitreader mc core
-USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
+USEDLIBS = clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(LEVEL)/Makefile.common
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 46e4ae946f19..64c3a213cd78 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,4 +1,3 @@
add_subdirectory(CIndex)
add_subdirectory(c-index-test)
add_subdirectory(driver)
-add_subdirectory(index-test)
diff --git a/tools/Makefile b/tools/Makefile
index a30932b8996f..ce3e4cd308e4 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -8,6 +8,6 @@
##===----------------------------------------------------------------------===##
LEVEL := ../../..
-DIRS := driver index-test CIndex c-index-test
+DIRS := driver CIndex c-index-test
include $(LEVEL)/Makefile.common
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 01a0d439297b..4ef390413972 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
/******************************************************************************/
/* Utility functions. */
@@ -38,6 +39,99 @@ static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
return 1;
}
+void free_remapped_files(struct CXUnsavedFile *unsaved_files,
+ int num_unsaved_files) {
+ int i;
+ for (i = 0; i != num_unsaved_files; ++i) {
+ free((char *)unsaved_files[i].Filename);
+ free((char *)unsaved_files[i].Contents);
+ }
+}
+
+int parse_remapped_files(int argc, const char **argv, int start_arg,
+ struct CXUnsavedFile **unsaved_files,
+ int *num_unsaved_files) {
+ int i;
+ int arg;
+ int prefix_len = strlen("-remap-file=");
+ *unsaved_files = 0;
+ *num_unsaved_files = 0;
+
+ /* Count the number of remapped files. */
+ for (arg = start_arg; arg < argc; ++arg) {
+ if (strncmp(argv[arg], "-remap-file=", prefix_len))
+ break;
+
+ ++*num_unsaved_files;
+ }
+
+ if (*num_unsaved_files == 0)
+ return 0;
+
+ *unsaved_files
+ = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
+ *num_unsaved_files);
+ for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
+ struct CXUnsavedFile *unsaved = *unsaved_files + i;
+ const char *arg_string = argv[arg] + prefix_len;
+ int filename_len;
+ char *filename;
+ char *contents;
+ FILE *to_file;
+ const char *semi = strchr(arg_string, ';');
+ if (!semi) {
+ fprintf(stderr,
+ "error: -remap-file=from;to argument is missing semicolon\n");
+ free_remapped_files(*unsaved_files, i);
+ *unsaved_files = 0;
+ *num_unsaved_files = 0;
+ return -1;
+ }
+
+ /* Open the file that we're remapping to. */
+ to_file = fopen(semi + 1, "r");
+ if (!to_file) {
+ fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
+ semi + 1);
+ free_remapped_files(*unsaved_files, i);
+ *unsaved_files = 0;
+ *num_unsaved_files = 0;
+ return -1;
+ }
+
+ /* Determine the length of the file we're remapping to. */
+ fseek(to_file, 0, SEEK_END);
+ unsaved->Length = ftell(to_file);
+ fseek(to_file, 0, SEEK_SET);
+
+ /* Read the contents of the file we're remapping to. */
+ contents = (char *)malloc(unsaved->Length + 1);
+ if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
+ fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
+ (feof(to_file) ? "EOF" : "error"), semi + 1);
+ fclose(to_file);
+ free_remapped_files(*unsaved_files, i);
+ *unsaved_files = 0;
+ *num_unsaved_files = 0;
+ return -1;
+ }
+ contents[unsaved->Length] = 0;
+ unsaved->Contents = contents;
+
+ /* Close the file. */
+ fclose(to_file);
+
+ /* Copy the file name that we're remapping from. */
+ filename_len = semi - arg_string;
+ filename = (char *)malloc(filename_len + 1);
+ memcpy(filename, arg_string, filename_len);
+ filename[filename_len] = 0;
+ unsaved->Filename = filename;
+ }
+
+ return 0;
+}
+
/******************************************************************************/
/* Pretty-printing. */
/******************************************************************************/
@@ -46,86 +140,96 @@ static void PrintCursor(CXCursor Cursor) {
if (clang_isInvalid(Cursor.kind))
printf("Invalid Cursor => %s", clang_getCursorKindSpelling(Cursor.kind));
else {
- CXDecl DeclReferenced;
CXString string;
+ CXCursor Referenced;
+ unsigned line, column;
string = clang_getCursorSpelling(Cursor);
printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind),
clang_getCString(string));
clang_disposeString(string);
- DeclReferenced = clang_getCursorDecl(Cursor);
- if (DeclReferenced)
- printf(":%d:%d", clang_getDeclLine(DeclReferenced),
- clang_getDeclColumn(DeclReferenced));
+
+ Referenced = clang_getCursorReferenced(Cursor);
+ if (!clang_equalCursors(Referenced, clang_getNullCursor())) {
+ CXSourceLocation Loc = clang_getCursorLocation(Referenced);
+ clang_getInstantiationLocation(Loc, 0, &line, &column);
+ printf(":%d:%d", line, column);
+ }
+
+ if (clang_isCursorDefinition(Cursor))
+ printf(" (Definition)");
}
}
static const char* GetCursorSource(CXCursor Cursor) {
- const char *source = clang_getCursorSource(Cursor);
+ CXSourceLocation Loc = clang_getCursorLocation(Cursor);
+ const char *source;
+ CXFile file;
+ clang_getInstantiationLocation(Loc, &file, 0, 0);
+ source = clang_getFileName(file);
if (!source)
return "<invalid loc>";
return basename(source);
}
/******************************************************************************/
-/* Logic for testing clang_loadTranslationUnit(). */
+/* Logic for testing traversal. */
/******************************************************************************/
static const char *FileCheckPrefix = "CHECK";
-static void PrintDeclExtent(CXDecl Dcl) {
- CXSourceExtent extent = clang_getDeclExtent(Dcl);
- printf(" [Extent=%d:%d:%d:%d]", extent.begin.line, extent.begin.column,
- extent.end.line, extent.end.column);
-}
-
-static void DeclVisitor(CXDecl Dcl, CXCursor Cursor, CXClientData Filter) {
- if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
- CXString string;
- printf("// %s: %s:%d:%d: ", FileCheckPrefix,
- GetCursorSource(Cursor),
- clang_getCursorLine(Cursor),
- clang_getCursorColumn(Cursor));
- PrintCursor(Cursor);
-
- string = clang_getDeclSpelling(Dcl);
- printf(" [Context=%s]", clang_getCString(string));
- clang_disposeString(string);
-
- PrintDeclExtent(clang_getCursorDecl(Cursor));
+static void PrintCursorExtent(CXCursor C) {
+ CXSourceRange extent = clang_getCursorExtent(C);
+ CXFile begin_file, end_file;
+ unsigned begin_line, begin_column, end_line, end_column;
+
+ clang_getInstantiationLocation(clang_getRangeStart(extent),
+ &begin_file, &begin_line, &begin_column);
+ clang_getInstantiationLocation(clang_getRangeEnd(extent),
+ &end_file, &end_line, &end_column);
+ if (!begin_file || !end_file)
+ return;
- printf("\n");
- }
+ printf(" [Extent=%d:%d:%d:%d]", begin_line, begin_column,
+ end_line, end_column);
}
-static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
- CXClientData Filter) {
- if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
- CXString string;
+/* Data used by all of the visitors. */
+typedef struct {
+ CXTranslationUnit TU;
+ enum CXCursorKind *Filter;
+} VisitorData;
+
+
+enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
+ CXCursor Parent,
+ CXClientData ClientData) {
+ VisitorData *Data = (VisitorData *)ClientData;
+ if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) {
+ CXSourceLocation Loc = clang_getCursorLocation(Cursor);
+ unsigned line, column;
+ clang_getInstantiationLocation(Loc, 0, &line, &column);
printf("// %s: %s:%d:%d: ", FileCheckPrefix,
- GetCursorSource(Cursor), clang_getCursorLine(Cursor),
- clang_getCursorColumn(Cursor));
+ GetCursorSource(Cursor), line, column);
PrintCursor(Cursor);
- string = clang_getTranslationUnitSpelling(Unit);
- printf(" [Context=%s]",
- basename(clang_getCString(string)));
- clang_disposeString(string);
-
- PrintDeclExtent(Cursor.decl);
-
- printf("\n");
-
- clang_loadDeclaration(Cursor.decl, DeclVisitor, 0);
+ PrintCursorExtent(Cursor);
+ printf("\n");
+ return CXChildVisit_Recurse;
}
+
+ return CXChildVisit_Continue;
}
-static void FunctionScanVisitor(CXTranslationUnit Unit, CXCursor Cursor,
- CXClientData Filter) {
+static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor,
+ CXCursor Parent,
+ CXClientData ClientData) {
const char *startBuf, *endBuf;
unsigned startLine, startColumn, endLine, endColumn, curLine, curColumn;
CXCursor Ref;
+ VisitorData *Data = (VisitorData *)ClientData;
- if (Cursor.kind != CXCursor_FunctionDefn)
- return;
+ if (Cursor.kind != CXCursor_FunctionDecl ||
+ !clang_isCursorDefinition(Cursor))
+ return CXChildVisit_Continue;
clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf,
&startLine, &startColumn,
@@ -135,6 +239,10 @@ static void FunctionScanVisitor(CXTranslationUnit Unit, CXCursor Cursor,
curColumn = startColumn;
while (startBuf < endBuf) {
+ CXSourceLocation Loc;
+ CXFile file;
+ const char *source = 0;
+
if (*startBuf == '\n') {
startBuf++;
curLine++;
@@ -142,47 +250,50 @@ static void FunctionScanVisitor(CXTranslationUnit Unit, CXCursor Cursor,
} else if (*startBuf != '\t')
curColumn++;
- Ref = clang_getCursor(Unit, clang_getCursorSource(Cursor),
- curLine, curColumn);
- if (Ref.kind == CXCursor_NoDeclFound) {
- /* Nothing found here; that's fine. */
- } else if (Ref.kind != CXCursor_FunctionDecl) {
- CXString string;
- printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
- curLine, curColumn);
- PrintCursor(Ref);
- string = clang_getDeclSpelling(Ref.decl);
- printf(" [Context:%s]\n", clang_getCString(string));
- clang_disposeString(string);
+ Loc = clang_getCursorLocation(Cursor);
+ clang_getInstantiationLocation(Loc, &file, 0, 0);
+ source = clang_getFileName(file);
+ if (source) {
+ CXSourceLocation RefLoc
+ = clang_getLocation(Data->TU, file, curLine, curColumn);
+ Ref = clang_getCursor(Data->TU, RefLoc);
+ if (Ref.kind == CXCursor_NoDeclFound) {
+ /* Nothing found here; that's fine. */
+ } else if (Ref.kind != CXCursor_FunctionDecl) {
+ printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
+ curLine, curColumn);
+ PrintCursor(Ref);
+ printf("\n");
+ }
}
startBuf++;
}
+
+ return CXChildVisit_Continue;
}
/******************************************************************************/
/* USR testing. */
/******************************************************************************/
-static void USRDeclVisitor(CXDecl D, CXCursor C, CXClientData Filter) {
- if (!Filter || (C.kind == *(enum CXCursorKind *)Filter)) {
- CXString USR = clang_getDeclUSR(C.decl);
+enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
+ CXClientData ClientData) {
+ VisitorData *Data = (VisitorData *)ClientData;
+ if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
+ CXString USR = clang_getCursorUSR(C);
if (!USR.Spelling) {
clang_disposeString(USR);
- return;
+ return CXChildVisit_Continue;
}
printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), USR.Spelling);
- PrintDeclExtent(C.decl);
+ PrintCursorExtent(C);
printf("\n");
clang_disposeString(USR);
- }
-}
-
-static void USRVisitor(CXTranslationUnit Unit, CXCursor Cursor,
- CXClientData Filter) {
- if (Cursor.decl) {
- /* USRDeclVisitor(Unit, Cursor.decl, Cursor, Filter);*/
- clang_loadDeclaration(Cursor.decl, USRDeclVisitor, 0);
- }
+
+ return CXChildVisit_Recurse;
+ }
+
+ return CXChildVisit_Continue;
}
/******************************************************************************/
@@ -191,10 +302,11 @@ static void USRVisitor(CXTranslationUnit Unit, CXCursor Cursor,
static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
const char *filter, const char *prefix,
- CXTranslationUnitIterator Visitor) {
+ CXCursorVisitor Visitor) {
enum CXCursorKind K = CXCursor_NotImplemented;
enum CXCursorKind *ck = &K;
-
+ VisitorData Data;
+
if (prefix)
FileCheckPrefix = prefix;
@@ -211,14 +323,16 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
return 1;
}
- clang_loadTranslationUnit(TU, Visitor, ck);
+ Data.TU = TU;
+ Data.Filter = ck;
+ clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data);
clang_disposeTranslationUnit(TU);
return 0;
}
int perform_test_load_tu(const char *file, const char *filter,
const char *prefix,
- CXTranslationUnitIterator Visitor) {
+ CXCursorVisitor Visitor) {
CXIndex Idx;
CXTranslationUnit TU;
Idx = clang_createIndex(/* excludeDeclsFromPCH */
@@ -232,11 +346,15 @@ int perform_test_load_tu(const char *file, const char *filter,
}
int perform_test_load_source(int argc, const char **argv, const char *filter,
- CXTranslationUnitIterator Visitor) {
+ CXCursorVisitor Visitor) {
const char *UseExternalASTs =
getenv("CINDEXTEST_USE_EXTERNAL_AST_GENERATION");
CXIndex Idx;
CXTranslationUnit TU;
+ struct CXUnsavedFile *unsaved_files = 0;
+ int num_unsaved_files = 0;
+ int result;
+
Idx = clang_createIndex(/* excludeDeclsFromPCH */
!strcmp(filter, "local") ? 1 : 0,
/* displayDiagnostics */ 1);
@@ -244,13 +362,22 @@ int perform_test_load_source(int argc, const char **argv, const char *filter,
if (UseExternalASTs && strlen(UseExternalASTs))
clang_setUseExternalASTGeneration(Idx, 1);
- TU = clang_createTranslationUnitFromSourceFile(Idx, 0, argc, argv);
+ if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files))
+ return -1;
+
+ TU = clang_createTranslationUnitFromSourceFile(Idx, 0,
+ argc - num_unsaved_files,
+ argv + num_unsaved_files,
+ num_unsaved_files,
+ unsaved_files);
if (!TU) {
fprintf(stderr, "Unable to load translation unit!\n");
return 1;
}
- return perform_test_load(Idx, TU, filter, NULL, Visitor);
+ result = perform_test_load(Idx, TU, filter, NULL, Visitor);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ return result;
}
/******************************************************************************/
@@ -277,6 +404,7 @@ static int perform_file_scan(const char *ast_file, const char *source_file,
FILE *fp;
unsigned line;
CXCursor prevCursor;
+ CXFile file;
unsigned printed;
unsigned start_line, start_col, last_line, last_col;
size_t i;
@@ -301,6 +429,7 @@ static int perform_file_scan(const char *ast_file, const char *source_file,
start_line = last_line = 1;
start_col = last_col = 1;
+ file = clang_getFile(TU, source_file);
while (!feof(fp)) {
size_t len = 0;
int c;
@@ -315,7 +444,7 @@ static int perform_file_scan(const char *ast_file, const char *source_file,
for (i = 0; i < len ; ++i) {
CXCursor cursor;
- cursor = clang_getCursor(TU, source_file, line, i+1);
+ cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, i+1));
if (!clang_equalCursors(cursor, prevCursor) &&
prevCursor.kind != CXCursor_InvalidFile) {
@@ -454,99 +583,6 @@ void print_completion_result(CXCompletionResult *completion_result,
fprintf(file, "\n");
}
-void free_remapped_files(struct CXUnsavedFile *unsaved_files,
- int num_unsaved_files) {
- int i;
- for (i = 0; i != num_unsaved_files; ++i) {
- free((char *)unsaved_files[i].Filename);
- free((char *)unsaved_files[i].Contents);
- }
-}
-
-int parse_remapped_files(int argc, const char **argv, int start_arg,
- struct CXUnsavedFile **unsaved_files,
- int *num_unsaved_files) {
- int i;
- int arg;
- int prefix_len = strlen("-remap-file=");
- *unsaved_files = 0;
- *num_unsaved_files = 0;
-
- /* Count the number of remapped files. */
- for (arg = start_arg; arg < argc; ++arg) {
- if (strncmp(argv[arg], "-remap-file=", prefix_len))
- break;
-
- ++*num_unsaved_files;
- }
-
- if (*num_unsaved_files == 0)
- return 0;
-
- *unsaved_files
- = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
- *num_unsaved_files);
- for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
- struct CXUnsavedFile *unsaved = *unsaved_files + i;
- const char *arg_string = argv[arg] + prefix_len;
- int filename_len;
- char *filename;
- char *contents;
- FILE *to_file;
- const char *semi = strchr(arg_string, ';');
- if (!semi) {
- fprintf(stderr,
- "error: -remap-file=from;to argument is missing semicolon\n");
- free_remapped_files(*unsaved_files, i);
- *unsaved_files = 0;
- *num_unsaved_files = 0;
- return -1;
- }
-
- /* Open the file that we're remapping to. */
- to_file = fopen(semi + 1, "r");
- if (!to_file) {
- fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
- semi + 1);
- free_remapped_files(*unsaved_files, i);
- *unsaved_files = 0;
- *num_unsaved_files = 0;
- return -1;
- }
-
- /* Determine the length of the file we're remapping to. */
- fseek(to_file, 0, SEEK_END);
- unsaved->Length = ftell(to_file);
- fseek(to_file, 0, SEEK_SET);
-
- /* Read the contents of the file we're remapping to. */
- contents = (char *)malloc(unsaved->Length + 1);
- if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
- fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
- (feof(to_file) ? "EOF" : "error"), semi + 1);
- fclose(to_file);
- free_remapped_files(*unsaved_files, i);
- *unsaved_files = 0;
- *num_unsaved_files = 0;
- return -1;
- }
- contents[unsaved->Length] = 0;
- unsaved->Contents = contents;
-
- /* Close the file. */
- fclose(to_file);
-
- /* Copy the file name that we're remapping from. */
- filename_len = semi - arg_string;
- filename = (char *)malloc(filename_len + 1);
- memcpy(filename, arg_string, filename_len);
- filename[filename_len] = 0;
- unsaved->Filename = filename;
- }
-
- return 0;
-}
-
int perform_code_completion(int argc, const char **argv) {
const char *input = argv[1];
char *filename = 0;
@@ -586,13 +622,80 @@ int perform_code_completion(int argc, const char **argv) {
return 0;
}
+typedef struct {
+ char *filename;
+ unsigned line;
+ unsigned column;
+} CursorSourceLocation;
+
+int inspect_cursor_at(int argc, const char **argv) {
+ CXIndex CIdx;
+ int errorCode;
+ struct CXUnsavedFile *unsaved_files = 0;
+ int num_unsaved_files = 0;
+ CXTranslationUnit TU;
+ CXCursor Cursor;
+ CursorSourceLocation *Locations = 0;
+ unsigned NumLocations = 0, Loc;
+
+ /* Count the number of locations. */
+ while (strstr(argv[NumLocations+1], "-cursor-at=") == argv[NumLocations+1])
+ ++NumLocations;
+
+ /* Parse the locations. */
+ assert(NumLocations > 0 && "Unable to count locations?");
+ Locations = (CursorSourceLocation *)malloc(
+ NumLocations * sizeof(CursorSourceLocation));
+ for (Loc = 0; Loc < NumLocations; ++Loc) {
+ const char *input = argv[Loc + 1] + strlen("-cursor-at=");
+ if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
+ &Locations[Loc].line,
+ &Locations[Loc].column)))
+ return errorCode;
+ }
+
+ if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
+ &num_unsaved_files))
+ return -1;
+
+ CIdx = clang_createIndex(0, 1);
+ TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1],
+ argc - num_unsaved_files - 2 - NumLocations,
+ argv + num_unsaved_files + 1 + NumLocations,
+ num_unsaved_files,
+ unsaved_files);
+ if (!TU) {
+ fprintf(stderr, "unable to parse input\n");
+ return -1;
+ }
+
+ for (Loc = 0; Loc < NumLocations; ++Loc) {
+ CXFile file = clang_getFile(TU, Locations[Loc].filename);
+ if (!file)
+ continue;
+
+ Cursor = clang_getCursor(TU,
+ clang_getLocation(TU, file, Locations[Loc].line,
+ Locations[Loc].column));
+ PrintCursor(Cursor);
+ printf("\n");
+ free(Locations[Loc].filename);
+ }
+
+ clang_disposeTranslationUnit(TU);
+ clang_disposeIndex(CIdx);
+ free(Locations);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ return 0;
+}
+
/******************************************************************************/
/* Command line processing. */
/******************************************************************************/
-static CXTranslationUnitIterator GetVisitor(const char *s) {
+static CXCursorVisitor GetVisitor(const char *s) {
if (s[0] == '\0')
- return TranslationUnitVisitor;
+ return FilteredPrintingVisitor;
if (strcmp(s, "-usrs") == 0)
return USRVisitor;
return NULL;
@@ -601,6 +704,7 @@ static CXTranslationUnitIterator GetVisitor(const char *s) {
static void print_usage(void) {
fprintf(stderr,
"usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
+ " c-index-test -cursor-at=<site> <compiler arguments>\n"
" c-index-test -test-file-scan <AST file> <source file> "
"[FileCheck prefix]\n"
" c-index-test -test-load-tu <AST file> <symbol filter> "
@@ -608,7 +712,8 @@ static void print_usage(void) {
" c-index-test -test-load-tu-usrs <AST file> <symbol filter> "
"[FileCheck prefix]\n"
" c-index-test -test-load-source <symbol filter> {<args>}*\n"
- " c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n\n"
+ " c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n\n");
+ fprintf(stderr,
" <symbol filter> values:\n%s",
" all - load all symbols, including those from PCH\n"
" local - load all symbols except those in PCH\n"
@@ -623,13 +728,15 @@ static void print_usage(void) {
int main(int argc, const char **argv) {
if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1])
return perform_code_completion(argc, argv);
+ if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])
+ return inspect_cursor_at(argc, argv);
else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
- CXTranslationUnitIterator I = GetVisitor(argv[1] + 13);
+ CXCursorVisitor I = GetVisitor(argv[1] + 13);
if (I)
return perform_test_load_tu(argv[2], argv[3], argc >= 5 ? argv[4] : 0, I);
}
else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
- CXTranslationUnitIterator I = GetVisitor(argv[1] + 17);
+ CXCursorVisitor I = GetVisitor(argv[1] + 17);
if (I)
return perform_test_load_source(argc - 3, argv + 3, argv[2], I);
}
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 0815554521f0..90fb09c0d9a8 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -44,4 +44,4 @@ install(TARGETS clang
RUNTIME DESTINATION bin)
# Create the clang++ symlink at installation time.
-install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E ${CLANGXX_LINK_OR_COPY} \"${CMAKE_INSTALL_PREFIX}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}\" \"${CMAKE_INSTALL_PREFIX}/bin/clang++${CMAKE_EXECUTABLE_SUFFIX}\")")
+install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E ${CLANGXX_LINK_OR_COPY} \"${CMAKE_INSTALL_PREFIX}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}\" \"\$ENV{DESTDIR}/\${CMAKE_INSTALL_PREFIX}/bin/clang++${CMAKE_EXECUTABLE_SUFFIX}\")")
diff --git a/tools/driver/Makefile b/tools/driver/Makefile
index 7dab2ac92378..6ec82918c075 100644
--- a/tools/driver/Makefile
+++ b/tools/driver/Makefile
@@ -9,7 +9,9 @@
LEVEL = ../../../..
TOOLNAME = clang
+ifndef CLANG_IS_PRODUCTION
TOOLALIAS = clang++
+endif
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CXXFLAGS = -fno-rtti
diff --git a/utils/OptionalTests/Extra/README.txt b/utils/OptionalTests/Extra/README.txt
new file mode 100644
index 000000000000..565241b51b7f
--- /dev/null
+++ b/utils/OptionalTests/Extra/README.txt
@@ -0,0 +1,3 @@
+This directory is for extra unit style tests following the structure of
+clang/tests, but which are not portable or not suitable for inclusion in the
+regular test suite.
diff --git a/utils/OptionalTests/Extra/Runtime/darwin-clang_rt.c b/utils/OptionalTests/Extra/Runtime/darwin-clang_rt.c
new file mode 100644
index 000000000000..d22c0bd0bca0
--- /dev/null
+++ b/utils/OptionalTests/Extra/Runtime/darwin-clang_rt.c
@@ -0,0 +1,338 @@
+/* This file tests that we can succesfully call each compiler-rt function. It is
+ designed to check that the runtime libraries are available for linking and
+ that they contain the expected contents. It is not designed to test the
+ correctness of the individual functions in compiler-rt.
+
+ This test is assumed to be run on a 10.6 machine. The two environment
+ variables below should be set to 10.4 and 10.5 machines which can be directly
+ ssh/rsync'd to in order to actually test the executables can run on the
+ desired targets.
+*/
+
+// RUN: export TENFOUR_X86_MACHINE=localhost
+// RUN: export TENFIVE_X86_MACHINE=localhost
+// RUN: export ARM_MACHINE=localhost
+// RUN: export ARM_SYSROOT=$(xcodebuild -sdk iphoneos -version Path)
+
+// RUN: echo iPhoneOS, ARM, v6, thumb
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv6 -mthumb -c %s -o %t.o
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv6 -mthumb -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: rsync -arv %t $ARM_MACHINE:/tmp/a.out
+// RUN: ssh $ARM_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo iPhoneOS, ARM, v6, no-thumb
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv6 -mno-thumb -c %s -o %t.o
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv6 -mno-thumb -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: rsync -arv %t $ARM_MACHINE:/tmp/a.out
+// RUN: ssh $ARM_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo iPhoneOS, ARM, v7, thumb
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv7 -mthumb -c %s -o %t.o
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv7 -mthumb -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: rsync -arv %t $ARM_MACHINE:/tmp/a.out
+// RUN: ssh $ARM_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo iPhoneOS, ARM, v7, no-thumb
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv7 -mno-thumb -c %s -o %t.o
+// RUN: %clang -isysroot $ARM_SYSROOT -arch armv7 -mno-thumb -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: rsync -arv %t $ARM_MACHINE:/tmp/a.out
+// RUN: ssh $ARM_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo 10.4, i386
+// RUN: %clang -arch i386 -mmacosx-version-min=10.4 -c %s -o %t.o
+// RUN: %clang -arch i386 -mmacosx-version-min=10.4 -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: %t
+// RUN: echo
+
+// RUN: rsync -arv %t $TENFOUR_X86_MACHINE:/tmp/a.out
+// RUN: ssh $TENFOUR_X86_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUX: rsync -arv %t $TENFIVE_X86_MACHINE:/tmp/a.out
+// RUX: ssh $TENFIVE_X86_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo 10.5, i386
+// RUN: %clang -arch i386 -mmacosx-version-min=10.5 -c %s -o %t.o
+// RUN: %clang -arch i386 -mmacosx-version-min=10.5 -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: %t
+// RUN: echo
+
+// RUN: rsync -arv %t $TENFIVE_X86_MACHINE:/tmp/a.out
+// RUN: ssh $TENFIVE_X86_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo 10.6, i386
+// RUN: %clang -arch i386 -mmacosx-version-min=10.6 -c %s -o %t.o
+// RUN: %clang -arch i386 -mmacosx-version-min=10.6 -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: %t
+// RUN: echo
+
+// RUN: echo 10.4, x86_64
+// RUN: %clang -arch x86_64 -mmacosx-version-min=10.4 -c %s -o %t.o
+// RUN: %clang -arch x86_64 -mmacosx-version-min=10.4 -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: %t
+// RUN: echo
+
+// RUN: rsync -arv %t $TENFOUR_X86_MACHINE:/tmp/a.out
+// RUN: ssh $TENFOUR_X86_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: rsync -arv %t $TENFIVE_X86_MACHINE:/tmp/a.out
+// RUN: ssh $TENFIVE_X86_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo 10.5, x86_64
+// RUN: %clang -arch x86_64 -mmacosx-version-min=10.5 -c %s -o %t.o
+// RUN: %clang -arch x86_64 -mmacosx-version-min=10.5 -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: %t
+// RUN: echo
+
+// RUN: rsync -arv %t $TENFIVE_X86_MACHINE:/tmp/a.out
+// RUN: ssh $TENFIVE_X86_MACHINE /tmp/a.out
+// RUN: echo
+
+// RUN: echo 10.6, x86_64
+// RUN: %clang -arch x86_64 -mmacosx-version-min=10.6 -c %s -o %t.o
+// RUN: %clang -arch x86_64 -mmacosx-version-min=10.6 -v -Wl,-t,-v -o %t %t.o 1>&2
+// RUN: %t
+// RUN: echo
+
+#include <assert.h>
+#include <stdio.h>
+#include <sys/utsname.h>
+
+typedef int si_int;
+typedef unsigned su_int;
+
+typedef long long di_int;
+typedef unsigned long long du_int;
+
+// Integral bit manipulation
+
+di_int __ashldi3(di_int a, si_int b); // a << b
+di_int __ashrdi3(di_int a, si_int b); // a >> b arithmetic (sign fill)
+di_int __lshrdi3(di_int a, si_int b); // a >> b logical (zero fill)
+
+si_int __clzsi2(si_int a); // count leading zeros
+si_int __clzdi2(di_int a); // count leading zeros
+si_int __ctzsi2(si_int a); // count trailing zeros
+si_int __ctzdi2(di_int a); // count trailing zeros
+
+si_int __ffsdi2(di_int a); // find least significant 1 bit
+
+si_int __paritysi2(si_int a); // bit parity
+si_int __paritydi2(di_int a); // bit parity
+
+si_int __popcountsi2(si_int a); // bit population
+si_int __popcountdi2(di_int a); // bit population
+
+// Integral arithmetic
+
+di_int __negdi2 (di_int a); // -a
+di_int __muldi3 (di_int a, di_int b); // a * b
+di_int __divdi3 (di_int a, di_int b); // a / b signed
+du_int __udivdi3 (du_int a, du_int b); // a / b unsigned
+di_int __moddi3 (di_int a, di_int b); // a % b signed
+du_int __umoddi3 (du_int a, du_int b); // a % b unsigned
+du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b
+
+// Integral arithmetic with trapping overflow
+
+si_int __absvsi2(si_int a); // abs(a)
+di_int __absvdi2(di_int a); // abs(a)
+
+si_int __negvsi2(si_int a); // -a
+di_int __negvdi2(di_int a); // -a
+
+si_int __addvsi3(si_int a, si_int b); // a + b
+di_int __addvdi3(di_int a, di_int b); // a + b
+
+si_int __subvsi3(si_int a, si_int b); // a - b
+di_int __subvdi3(di_int a, di_int b); // a - b
+
+si_int __mulvsi3(si_int a, si_int b); // a * b
+di_int __mulvdi3(di_int a, di_int b); // a * b
+
+// Integral comparison: a < b -> 0
+// a == b -> 1
+// a > b -> 2
+
+si_int __cmpdi2 (di_int a, di_int b);
+si_int __ucmpdi2(du_int a, du_int b);
+
+// Integral / floating point conversion
+
+di_int __fixsfdi( float a);
+di_int __fixdfdi( double a);
+di_int __fixxfdi(long double a);
+
+su_int __fixunssfsi( float a);
+su_int __fixunsdfsi( double a);
+su_int __fixunsxfsi(long double a);
+
+du_int __fixunssfdi( float a);
+du_int __fixunsdfdi( double a);
+du_int __fixunsxfdi(long double a);
+
+float __floatdisf(di_int a);
+double __floatdidf(di_int a);
+long double __floatdixf(di_int a);
+
+float __floatundisf(du_int a);
+double __floatundidf(du_int a);
+long double __floatundixf(du_int a);
+
+// Floating point raised to integer power
+
+float __powisf2( float a, si_int b); // a ^ b
+double __powidf2( double a, si_int b); // a ^ b
+long double __powixf2(long double a, si_int b); // a ^ b
+
+// Complex arithmetic
+
+// (a + ib) * (c + id)
+
+ float _Complex __mulsc3( float a, float b, float c, float d);
+ double _Complex __muldc3(double a, double b, double c, double d);
+long double _Complex __mulxc3(long double a, long double b,
+ long double c, long double d);
+
+// (a + ib) / (c + id)
+
+ float _Complex __divsc3( float a, float b, float c, float d);
+ double _Complex __divdc3(double a, double b, double c, double d);
+long double _Complex __divxc3(long double a, long double b,
+ long double c, long double d);
+
+#ifndef __arm
+#define HAS_LONG_DOUBLE
+#endif
+
+int main(int argc, char **argv) {
+ du_int du_tmp;
+ struct utsname name;
+#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ const char *target_name = "OS X";
+ unsigned target_version = __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__;
+ unsigned target_maj = target_version / 100;
+ unsigned target_min = (target_version / 10) % 10;
+ unsigned target_micro = target_version % 10;
+#else
+ const char *target_name = "iPhoneOS";
+ unsigned target_version = __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__;
+ unsigned target_maj = target_version / 10000;
+ unsigned target_min = (target_version / 100) % 100;
+ unsigned target_micro = target_version % 100;
+#endif
+
+ if (uname(&name))
+ return 1;
+
+ fprintf(stderr, "%s: clang_rt test:\n", argv[0]);
+ fprintf(stderr, " target : %s %d.%d.%d\n\n", target_name,
+ target_maj, target_min, target_micro);
+ fprintf(stderr, " sysname : %s\n", name.sysname);
+ fprintf(stderr, " nodename: %s\n", name.nodename);
+ fprintf(stderr, " release : %s\n", name.release);
+ fprintf(stderr, " version : %s\n", name.version);
+ fprintf(stderr, " machine : %s\n", name.machine);
+
+ assert(__ashldi3(1, 1) == 2);
+ assert(__ashrdi3(2, 1) == 1);
+ assert(__lshrdi3(2, 1) == 1);
+ assert(__clzsi2(1) == 31);
+ assert(__clzdi2(1) == 63);
+ assert(__ctzsi2(2) == 1);
+ assert(__ctzdi2(2) == 1);
+ assert(__ffsdi2(12) == 3);
+ assert(__paritysi2(13) == 1);
+ assert(__paritydi2(13) == 1);
+ assert(__popcountsi2(13) == 3);
+ assert(__popcountdi2(13) == 3);
+ assert(__negdi2(3) == -3);
+ assert(__muldi3(2,2) == 4);
+ assert(__divdi3(-4,2) == -2);
+ assert(__udivdi3(4,2) == 2);
+ assert(__moddi3(3,2) == 1);
+ assert(__umoddi3(3,2) == 1);
+ assert(__udivmoddi4(5,2,&du_tmp) == 2 && du_tmp == 1);
+ assert(__absvsi2(-2) == 2);
+ assert(__absvdi2(-2) == 2);
+ assert(__negvsi2(2) == -2);
+ assert(__negvdi2(2) == -2);
+ assert(__addvsi3(2, 3) == 5);
+ assert(__addvdi3(2, 3) == 5);
+ assert(__subvsi3(2, 3) == -1);
+ assert(__subvdi3(2, 3) == -1);
+ assert(__mulvsi3(2, 3) == 6);
+ assert(__mulvdi3(2, 3) == 6);
+ assert(__cmpdi2(3, 2) == 2);
+ assert(__ucmpdi2(3, 2) == 2);
+ assert(__fixsfdi(2.0) == 2);
+ assert(__fixdfdi(2.0) == 2);
+ assert(__fixunssfsi(2.0) == 2);
+ assert(__fixunsdfsi(2.0) == 2);
+ assert(__fixunssfdi(2.0) == 2);
+ assert(__fixunsdfdi(2.0) == 2);
+ assert(__floatdisf(2) == 2.0);
+ assert(__floatdidf(2) == 2.0);
+ assert(__floatundisf(2) == 2.0);
+ assert(__floatundidf(2) == 2.0);
+ assert(__powisf2(2.0, 2) == 4.0);
+ assert(__powidf2(2.0, 2) == 4.0);
+
+ // FIXME: Clang/LLVM seems to be miscompiling _Complex currently, probably an
+ // ABI issue.
+#ifndef __arm
+ {
+ _Complex float a = __mulsc3(1.0, 2.0, 4.0, 8.0);
+ _Complex float b = (-12.0 + 16.0j);
+ fprintf(stderr, "a: (%f + %f), b: (%f + %f)\n",
+ __real a, __imag a, __real b, __imag b);
+ }
+ assert(__mulsc3(1.0, 2.0, 4.0, 8.0) == (-12.0 + 16.0j));
+ assert(__muldc3(1.0, 2.0, 4.0, 8.0) == (-12.0 + 16.0j));
+ assert(__divsc3(1.0, 2.0, 4.0, 8.0) == (0.25 + 0j));
+ assert(__divdc3(1.0, 2.0, 4.0, 8.0) == (0.25 + 0j));
+#endif
+
+#ifdef HAS_LONG_DOUBLE
+ assert(__divxc3(1.0, 2.0, 4.0, 8.0) == (0.25 + 0j));
+ assert(__fixunsxfdi(2.0) == 2);
+ assert(__fixunsxfsi(2.0) == 2);
+ assert(__fixxfdi(2.0) == 2);
+ assert(__floatdixf(2) == 2.0);
+ assert(__floatundixf(2) == 2);
+ assert(__mulxc3(1.0, 2.0, 4.0, 8.0) == (-12.0 + 16.0j));
+ assert(__powixf2(2.0, 2) == 4.0);
+#endif
+
+ // Test some calls which are used on armv6/thumb. The calls/prototypes are
+ // fake, it would be nice to test correctness, but mostly we just want to
+ // make sure we resolve symbols correctly.
+#if defined(__arm) && defined(__ARM_ARCH_6K__) && defined(__thumb__)
+ if (argc == 100) {
+ extern void __restore_vfp_d8_d15_regs(void), __save_vfp_d8_d15_regs(void);
+ extern void __switch8(void), __switchu8(void),
+ __switch16(void), __switch32(void);
+ extern void __addsf3vfp(void);
+
+ __addsf3vfp();
+ __restore_vfp_d8_d15_regs();
+ __save_vfp_d8_d15_regs();
+ __switch8();
+ __switchu8();
+ __switch16();
+ __switch32();
+ }
+#endif
+
+ fprintf(stderr, " OK!\n");
+
+ return 0;
+}
diff --git a/utils/OptionalTests/README.txt b/utils/OptionalTests/README.txt
new file mode 100644
index 000000000000..4ffdb3bb0d1a
--- /dev/null
+++ b/utils/OptionalTests/README.txt
@@ -0,0 +1,4 @@
+This is a dumping ground for additional tests which do not fit cleanly into the
+clang regression tests. For example, tests which are not portable, require
+additional software or configuration, take an excessive time to run, or are
+flaky can be kept here.
diff --git a/utils/OptionalTests/lit.cfg b/utils/OptionalTests/lit.cfg
new file mode 100644
index 000000000000..592c42472525
--- /dev/null
+++ b/utils/OptionalTests/lit.cfg
@@ -0,0 +1,26 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+# Load the main clang test config so we can leech its clang finding logic.
+lit.load_config(config, os.path.join(os.path.dirname(__file__),
+ '..', '..', 'test', 'lit.cfg'))
+assert config.clang, "Failed to set clang!?"
+
+# name: The name of this test suite.
+config.name = 'Clang-Opt-Tests'
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = []
+
+# Reset these from the Clang config.
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# test_exec_root: The root path where tests should be run.
+clang_obj_root = getattr(config, 'clang_obj_root', None)
+if clang_obj_root is not None:
+ config.test_exec_root = os.path.join(clang_obj_root, 'utils',
+ 'OptionalTests')
+
diff --git a/www/analyzer/scan-build.html b/www/analyzer/scan-build.html
index 92a4c3e5e93b..fd05af021bd9 100644
--- a/www/analyzer/scan-build.html
+++ b/www/analyzer/scan-build.html
@@ -81,7 +81,7 @@ built using <tt>xcodebuild</tt>.<p>
$ <span class="code_highlight">scan-build</span> <i>[scan-build options]</i> <span class="code_highlight">&lt;command&gt;</span> <i>[command options]</i>
</pre>
-<p>Operationally, <tt>scan-build</tt> literally runs <command> with all of the
+<p>Operationally, <tt>scan-build</tt> literally runs &lt;command&gt; with all of the
subsequent options passed to it. For example, one can pass <nobr><tt>-j4</tt></nobr> to
<tt>make</tt> get a parallel build over 4 cores:</p>
diff --git a/www/hacking.html b/www/hacking.html
index ec9cd97cbaab..3bbc0eaea84b 100644
--- a/www/hacking.html
+++ b/www/hacking.html
@@ -19,6 +19,7 @@
on Clang for developers who are new to the Clang and/or LLVM
codebases.</p>
<ul>
+ <li><a href="#style">Coding Standards</a></li>
<li><a href="#docs">Developer Documentation</a></li>
<li><a href="#debugging">Debugging</a></li>
<li><a href="#testing">Testing</a></li>
@@ -31,6 +32,27 @@
</ul>
<!--=====================================================================-->
+ <h2 id="docs">Coding Standards</h2>
+ <!--=====================================================================-->
+
+ <p>Clang follows the
+ LLVM <a href="http://llvm.org/docs/CodingStandards.html">Coding
+ Standards</a>. When submitting patches, please take care to follow these standards
+ and to match the style of the code to that present in Clang (for example, in
+ terms of indentation, bracing, and statement spacing).</p>
+
+ <p>Clang has a few additional coding standards:</p>
+ <ul>
+ <li><i>cstdio is forbidden</i>: library code should not output diagnostics
+ or other information using <tt>cstdio</tt>; debugging routines should
+ use <tt>llvm::errs()</tt>. Other uses of <tt>cstdio</tt> impose behavior
+ upon clients and block integrating Clang as a library. Libraries should
+ support <tt>raw_ostream</tt> based interfaces for textual
+ output. See <a href="http://llvm.org/docs/CodingStandards.html#ll_raw_ostream">Coding
+ Standards</a>.</li>
+ </ul>
+
+ <!--=====================================================================-->
<h2 id="docs">Developer Documentation</h2>
<!--=====================================================================-->