aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
commitb3d5a323a5ca92ea73443499cee2f15db1ff0fb3 (patch)
tree60a1694bec5a44d15456acc880cb2f91619f66aa
parent8f57cb0305232cb53fff00ef151ca716766f3437 (diff)
downloadsrc-b3d5a323a5ca92ea73443499cee2f15db1ff0fb3.tar.gz
src-b3d5a323a5ca92ea73443499cee2f15db1ff0fb3.zip
Update clang to r89205.
Notes
Notes: svn path=/vendor/clang/dist/; revision=199482
-rw-r--r--CMakeLists.txt5
-rw-r--r--Makefile6
-rw-r--r--NOTES.txt2
-rw-r--r--TODO.txt9
-rw-r--r--clang.xcodeproj/project.pbxproj14
-rw-r--r--docs/UsersManual.html2
-rw-r--r--include/clang-c/Index.h353
-rw-r--r--include/clang/AST/ASTContext.h27
-rw-r--r--include/clang/AST/Attr.h2
-rw-r--r--include/clang/AST/CanonicalType.h17
-rw-r--r--include/clang/AST/Decl.h10
-rw-r--r--include/clang/AST/DeclBase.h11
-rw-r--r--include/clang/AST/DeclCXX.h364
-rw-r--r--include/clang/AST/DeclContextInternals.h3
-rw-r--r--include/clang/AST/DeclNodes.def4
-rw-r--r--include/clang/AST/DeclObjC.h32
-rw-r--r--include/clang/AST/DeclTemplate.h17
-rw-r--r--include/clang/AST/DeclarationName.h3
-rw-r--r--include/clang/AST/Expr.h11
-rw-r--r--include/clang/AST/ExprCXX.h2
-rw-r--r--include/clang/AST/RecordLayout.h2
-rw-r--r--include/clang/AST/Redeclarable.h3
-rw-r--r--include/clang/AST/TemplateBase.h100
-rw-r--r--include/clang/AST/Type.h327
-rw-r--r--include/clang/AST/TypeLoc.h12
-rw-r--r--include/clang/AST/TypeLocBuilder.h1
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h4
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h1
-rw-r--r--include/clang/Analysis/LocalCheckers.h4
-rw-r--r--include/clang/Analysis/ManagerRegistry.h53
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisContext.h1
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisManager.h5
-rw-r--r--include/clang/Analysis/PathSensitive/BugReporter.h16
-rw-r--r--include/clang/Analysis/PathSensitive/BugType.h15
-rw-r--r--include/clang/Analysis/PathSensitive/Checker.h101
-rw-r--r--include/clang/Analysis/PathSensitive/CheckerVisitor.def15
-rw-r--r--include/clang/Analysis/PathSensitive/CheckerVisitor.h36
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h32
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h122
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h22
-rw-r--r--include/clang/Analysis/PathSensitive/GRWorkList.h7
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h2
-rw-r--r--include/clang/Analysis/PathSensitive/SVals.h4
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h6
-rw-r--r--include/clang/Analysis/ProgramPoint.h64
-rw-r--r--include/clang/Analysis/Support/Optional.h3
-rw-r--r--include/clang/Analysis/Support/SaveAndRestore.h3
-rw-r--r--include/clang/Basic/Diagnostic.h15
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td7
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td25
-rw-r--r--include/clang/Basic/DiagnosticGroups.td24
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td8
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td10
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td97
-rw-r--r--include/clang/Basic/LangOptions.h7
-rw-r--r--include/clang/Basic/Makefile4
-rw-r--r--include/clang/Basic/TargetInfo.h48
-rw-r--r--include/clang/Basic/TargetOptions.h39
-rw-r--r--include/clang/CodeGen/CodeGenOptions.h75
-rw-r--r--include/clang/CodeGen/ModuleBuilder.h4
-rw-r--r--include/clang/Driver/Driver.h2
-rw-r--r--include/clang/Driver/Options.def4
-rw-r--r--include/clang/Driver/ToolChain.h11
-rw-r--r--include/clang/Driver/Types.h3
-rw-r--r--include/clang/Frontend/ASTConsumers.h10
-rw-r--r--include/clang/Frontend/Analyses.def3
-rw-r--r--include/clang/Frontend/AnalysisConsumer.h41
-rw-r--r--include/clang/Frontend/ChainedDiagnosticClient.h58
-rw-r--r--include/clang/Frontend/CommandLineSourceLoc.h3
-rw-r--r--include/clang/Frontend/CompilerInstance.h523
-rw-r--r--include/clang/Frontend/CompilerInvocation.h150
-rw-r--r--include/clang/Frontend/DependencyOutputOptions.h43
-rw-r--r--include/clang/Frontend/DiagnosticOptions.h30
-rw-r--r--include/clang/Frontend/FrontendAction.h215
-rw-r--r--include/clang/Frontend/FrontendActions.h216
-rw-r--r--include/clang/Frontend/FrontendOptions.h131
-rw-r--r--include/clang/Frontend/FrontendPluginRegistry.h23
-rw-r--r--include/clang/Frontend/HeaderSearchOptions.h87
-rw-r--r--include/clang/Frontend/PCHReader.h44
-rw-r--r--include/clang/Frontend/PCHWriter.h3
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h57
-rw-r--r--include/clang/Frontend/PreprocessorOutputOptions.h37
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h9
-rw-r--r--include/clang/Frontend/TypeXML.def6
-rw-r--r--include/clang/Frontend/Utils.h58
-rw-r--r--include/clang/Frontend/VerifyDiagnosticsClient.h82
-rw-r--r--include/clang/Lex/PTHManager.h3
-rw-r--r--include/clang/Lex/Preprocessor.h22
-rw-r--r--include/clang/Lex/Token.h63
-rw-r--r--include/clang/Parse/Action.h53
-rw-r--r--include/clang/Parse/AttributeList.h1
-rw-r--r--include/clang/Parse/DeclSpec.h11
-rw-r--r--include/clang/Parse/Ownership.h35
-rw-r--r--include/clang/Parse/Parser.h29
-rw-r--r--include/clang/Parse/Scope.h6
-rw-r--r--include/clang/Parse/Template.h183
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h146
-rw-r--r--include/clang/Sema/ParseAST.h8
-rw-r--r--lib/AST/ASTContext.cpp113
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/CXXInheritance.cpp29
-rw-r--r--lib/AST/Decl.cpp6
-rw-r--r--lib/AST/DeclBase.cpp32
-rw-r--r--lib/AST/DeclCXX.cpp86
-rw-r--r--lib/AST/DeclObjC.cpp47
-rw-r--r--lib/AST/DeclPrinter.cpp54
-rw-r--r--lib/AST/DeclTemplate.cpp7
-rw-r--r--lib/AST/DeclarationName.cpp5
-rw-r--r--lib/AST/Expr.cpp19
-rw-r--r--lib/AST/ExprCXX.cpp8
-rw-r--r--lib/AST/ExprConstant.cpp29
-rw-r--r--lib/AST/NestedNameSpecifier.cpp2
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp3
-rw-r--r--lib/AST/StmtDumper.cpp7
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/AST/TemplateBase.cpp14
-rw-r--r--lib/AST/Type.cpp710
-rw-r--r--lib/AST/TypePrinter.cpp728
-rw-r--r--lib/Analysis/AnalysisManager.cpp35
-rw-r--r--lib/Analysis/ArrayBoundChecker.cpp86
-rw-r--r--lib/Analysis/AttrNonNullChecker.cpp22
-rw-r--r--lib/Analysis/BadCallChecker.cpp25
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp2
-rw-r--r--lib/Analysis/BasicStore.cpp19
-rw-r--r--lib/Analysis/CFRefCount.cpp585
-rw-r--r--lib/Analysis/CMakeLists.txt17
-rw-r--r--lib/Analysis/CallGraph.cpp2
-rw-r--r--lib/Analysis/CastToStructChecker.cpp77
-rw-r--r--lib/Analysis/CheckSecuritySyntaxOnly.cpp52
-rw-r--r--lib/Analysis/CheckSizeofPointer.cpp72
-rw-r--r--lib/Analysis/DereferenceChecker.cpp161
-rw-r--r--lib/Analysis/DivZeroChecker.cpp21
-rw-r--r--lib/Analysis/ExplodedGraph.cpp2
-rw-r--r--lib/Analysis/FixedAddressChecker.cpp70
-rw-r--r--lib/Analysis/GRCoreEngine.cpp49
-rw-r--r--lib/Analysis/GRExprEngine.cpp448
-rw-r--r--lib/Analysis/GRExprEngineExperimentalChecks.cpp38
-rw-r--r--lib/Analysis/GRExprEngineExperimentalChecks.h26
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp115
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.h39
-rw-r--r--lib/Analysis/GRState.cpp6
-rw-r--r--lib/Analysis/LiveVariables.cpp12
-rw-r--r--lib/Analysis/MallocChecker.cpp218
-rw-r--r--lib/Analysis/ManagerRegistry.cpp (renamed from lib/Frontend/ManagerRegistry.cpp)2
-rw-r--r--lib/Analysis/MemRegion.cpp20
-rw-r--r--lib/Analysis/NSErrorChecker.cpp13
-rw-r--r--lib/Analysis/PointerArithChecker.cpp71
-rw-r--r--lib/Analysis/PointerSubChecker.cpp77
-rw-r--r--lib/Analysis/PthreadLockChecker.cpp141
-rw-r--r--lib/Analysis/RangeConstraintManager.cpp2
-rw-r--r--lib/Analysis/RegionStore.cpp25
-rw-r--r--lib/Analysis/ReturnPointerRangeChecker.cpp97
-rw-r--r--lib/Analysis/ReturnStackAddressChecker.cpp97
-rw-r--r--lib/Analysis/ReturnUndefChecker.cpp68
-rw-r--r--lib/Analysis/SVals.cpp10
-rw-r--r--lib/Analysis/SValuator.cpp3
-rw-r--r--lib/Analysis/Store.cpp22
-rw-r--r--lib/Analysis/UndefinedArgChecker.cpp29
-rw-r--r--lib/Analysis/UndefinedArraySubscriptChecker.cpp56
-rw-r--r--lib/Analysis/UndefinedAssignmentChecker.cpp5
-rw-r--r--lib/Analysis/VLASizeChecker.cpp153
-rw-r--r--lib/Basic/SourceManager.cpp4
-rw-r--r--lib/Basic/TargetInfo.cpp39
-rw-r--r--lib/Basic/Targets.cpp352
-rw-r--r--lib/Basic/Version.cpp4
-rw-r--r--lib/CodeGen/CGBlocks.cpp69
-rw-r--r--lib/CodeGen/CGBlocks.h3
-rw-r--r--lib/CodeGen/CGBuiltin.cpp21
-rw-r--r--lib/CodeGen/CGCXX.cpp631
-rw-r--r--lib/CodeGen/CGCXXClass.cpp3
-rw-r--r--lib/CodeGen/CGCXXExpr.cpp264
-rw-r--r--lib/CodeGen/CGCall.cpp13
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp265
-rw-r--r--lib/CodeGen/CGDebugInfo.h6
-rw-r--r--lib/CodeGen/CGDecl.cpp6
-rw-r--r--lib/CodeGen/CGExpr.cpp205
-rw-r--r--lib/CodeGen/CGExprAgg.cpp1
-rw-r--r--lib/CodeGen/CGExprConstant.cpp28
-rw-r--r--lib/CodeGen/CGExprScalar.cpp121
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp6
-rw-r--r--lib/CodeGen/CGObjCMac.cpp83
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp6
-rw-r--r--lib/CodeGen/CGRtti.cpp396
-rw-r--r--lib/CodeGen/CGStmt.cpp25
-rw-r--r--lib/CodeGen/CGVtable.cpp579
-rw-r--r--lib/CodeGen/CGVtable.h11
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp127
-rw-r--r--lib/CodeGen/CodeGenFunction.h57
-rw-r--r--lib/CodeGen/CodeGenModule.cpp74
-rw-r--r--lib/CodeGen/CodeGenModule.h75
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp2
-rw-r--r--lib/CodeGen/CodeGenTypes.h4
-rw-r--r--lib/CodeGen/GlobalDecl.h110
-rw-r--r--lib/CodeGen/Mangle.cpp70
-rw-r--r--lib/CodeGen/Mangle.h5
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp14
-rw-r--r--lib/CodeGen/TargetABIInfo.cpp39
-rw-r--r--lib/Driver/ToolChains.h13
-rw-r--r--lib/Driver/Tools.cpp132
-rw-r--r--lib/Driver/Types.cpp13
-rw-r--r--lib/Frontend/ASTUnit.cpp16
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp283
-rw-r--r--lib/Frontend/Backend.cpp91
-rw-r--r--lib/Frontend/CMakeLists.txt7
-rw-r--r--lib/Frontend/CompilerInstance.cpp403
-rw-r--r--lib/Frontend/CompilerInvocation.cpp548
-rw-r--r--lib/Frontend/DependencyFile.cpp44
-rw-r--r--lib/Frontend/DocumentXML.cpp4
-rw-r--r--lib/Frontend/FrontendAction.cpp225
-rw-r--r--lib/Frontend/FrontendActions.cpp281
-rw-r--r--lib/Frontend/FrontendOptions.cpp31
-rw-r--r--lib/Frontend/HTMLDiagnostics.cpp2
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp289
-rw-r--r--lib/Frontend/InitPreprocessor.cpp117
-rw-r--r--lib/Frontend/PCHReader.cpp186
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp9
-rw-r--r--lib/Frontend/PCHWriter.cpp22
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp4
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp10
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp3
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp26
-rw-r--r--lib/Frontend/RewriteObjC.cpp2
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp11
-rw-r--r--lib/Frontend/VerifyDiagnosticsClient.cpp344
-rw-r--r--lib/Frontend/Warnings.cpp18
-rw-r--r--lib/Headers/stdint.h615
-rw-r--r--lib/Index/ResolveLocation.cpp14
-rw-r--r--lib/Lex/Lexer.cpp8
-rw-r--r--lib/Lex/PPCaching.cpp2
-rw-r--r--lib/Lex/PPExpressions.cpp2
-rw-r--r--lib/Lex/PTHLexer.cpp40
-rw-r--r--lib/Lex/Preprocessor.cpp24
-rw-r--r--lib/Parse/AttributeList.cpp1
-rw-r--r--lib/Parse/DeclSpec.cpp10
-rw-r--r--lib/Parse/MinimalAction.cpp7
-rw-r--r--lib/Parse/ParseDecl.cpp1
-rw-r--r--lib/Parse/ParseDeclCXX.cpp17
-rw-r--r--lib/Parse/ParseExprCXX.cpp67
-rw-r--r--lib/Parse/ParseObjc.cpp51
-rw-r--r--lib/Parse/ParseTemplate.cpp163
-rw-r--r--lib/Parse/Parser.cpp1
-rw-r--r--lib/Rewrite/DeltaTree.cpp28
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp491
-rw-r--r--lib/Sema/JumpDiagnostics.cpp2
-rw-r--r--lib/Sema/Lookup.h392
-rw-r--r--lib/Sema/ParseAST.cpp17
-rw-r--r--lib/Sema/Sema.cpp338
-rw-r--r--lib/Sema/Sema.h507
-rw-r--r--lib/Sema/SemaAttr.cpp7
-rw-r--r--lib/Sema/SemaCXXCast.cpp150
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp29
-rw-r--r--lib/Sema/SemaChecking.cpp23
-rw-r--r--lib/Sema/SemaCodeComplete.cpp554
-rw-r--r--lib/Sema/SemaDecl.cpp249
-rw-r--r--lib/Sema/SemaDeclAttr.cpp44
-rw-r--r--lib/Sema/SemaDeclCXX.cpp745
-rw-r--r--lib/Sema/SemaDeclObjC.cpp81
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp374
-rw-r--r--lib/Sema/SemaExprCXX.cpp182
-rw-r--r--lib/Sema/SemaInit.cpp3
-rw-r--r--lib/Sema/SemaLookup.cpp433
-rw-r--r--lib/Sema/SemaOverload.cpp199
-rw-r--r--lib/Sema/SemaOverload.h8
-rw-r--r--lib/Sema/SemaStmt.cpp10
-rw-r--r--lib/Sema/SemaTemplate.cpp961
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp198
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp294
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp199
-rw-r--r--lib/Sema/SemaType.cpp5
-rw-r--r--lib/Sema/TreeTransform.h44
-rw-r--r--test/Analysis/CFDateGC.m10
-rw-r--r--test/Analysis/CFNumber.c8
-rw-r--r--test/Analysis/CFRetainRelease_NSAssertionHandler.m8
-rw-r--r--test/Analysis/CGColorSpace.c8
-rw-r--r--test/Analysis/CheckNSError.m8
-rw-r--r--test/Analysis/MissingDealloc.m2
-rw-r--r--test/Analysis/NSPanel.m8
-rw-r--r--test/Analysis/NSString.m19
-rw-r--r--test/Analysis/NSWindow.m8
-rw-r--r--test/Analysis/NoReturn.m8
-rw-r--r--test/Analysis/ObjCProperties.m8
-rw-r--r--test/Analysis/ObjCRetSigs.m4
-rw-r--r--test/Analysis/PR2599.m8
-rw-r--r--test/Analysis/PR2978.m2
-rw-r--r--test/Analysis/PR3991.m19
-rw-r--r--test/Analysis/array-struct.c12
-rw-r--r--test/Analysis/casts.c2
-rw-r--r--test/Analysis/casts.m4
-rw-r--r--test/Analysis/cfref_PR2519.c8
-rw-r--r--test/Analysis/cfref_rdar6080742.c8
-rw-r--r--test/Analysis/complex.c8
-rw-r--r--test/Analysis/concrete-address.c4
-rw-r--r--test/Analysis/conditional-op-missing-lhs.c2
-rw-r--r--test/Analysis/dead-stores.c10
-rw-r--r--test/Analysis/dead-stores.cpp10
-rw-r--r--test/Analysis/dead-stores.m2
-rw-r--r--test/Analysis/delegates.m4
-rw-r--r--test/Analysis/elementtype.c2
-rw-r--r--test/Analysis/exercise-ps.c4
-rw-r--r--test/Analysis/fields.c4
-rw-r--r--test/Analysis/func.c4
-rw-r--r--test/Analysis/malloc.c37
-rw-r--r--test/Analysis/misc-ps-64.m8
-rw-r--r--test/Analysis/misc-ps-basic-store.m2
-rw-r--r--test/Analysis/misc-ps-eager-assume.m2
-rw-r--r--test/Analysis/misc-ps-ranges.m6
-rw-r--r--test/Analysis/misc-ps-region-store-i386.m2
-rw-r--r--test/Analysis/misc-ps-region-store-x86_64.m2
-rw-r--r--test/Analysis/misc-ps-region-store.m45
-rw-r--r--test/Analysis/misc-ps.m38
-rw-r--r--test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m4
-rw-r--r--test/Analysis/no-exit-cfg.c4
-rw-r--r--test/Analysis/no-outofbounds.c5
-rw-r--r--test/Analysis/null-deref-ps-region.c2
-rw-r--r--test/Analysis/null-deref-ps.c8
-rw-r--r--test/Analysis/outofbound.c5
-rw-r--r--test/Analysis/override-werror.c4
-rw-r--r--test/Analysis/plist-output.m122
-rw-r--r--test/Analysis/pr4209.m14
-rw-r--r--test/Analysis/pr_2542_rdar_6793404.m4
-rw-r--r--test/Analysis/pr_4164.c4
-rw-r--r--test/Analysis/ptr-arith.c33
-rw-r--r--test/Analysis/rdar-6442306-1.m4
-rw-r--r--test/Analysis/rdar-6540084.m2
-rw-r--r--test/Analysis/rdar-6541136-region.c17
-rw-r--r--test/Analysis/rdar-6541136.c2
-rw-r--r--test/Analysis/rdar-6562655.m4
-rw-r--r--test/Analysis/rdar-6582778-basic-store.c2
-rw-r--r--test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m4
-rw-r--r--test/Analysis/rdar-7168531.m4
-rw-r--r--test/Analysis/refcnt_naming.m4
-rw-r--r--test/Analysis/region-1.m5
-rw-r--r--test/Analysis/retain-release-gc-only.m4
-rw-r--r--test/Analysis/retain-release.m2
-rw-r--r--test/Analysis/security-syntax-checks.m7
-rw-r--r--test/Analysis/sizeofpointer.c8
-rw-r--r--test/Analysis/stack-addr-ps.c4
-rw-r--r--test/Analysis/uninit-msg-expr.m2
-rw-r--r--test/Analysis/uninit-ps-rdar6145427.m2
-rw-r--r--test/Analysis/uninit-vals-ps.c2
-rw-r--r--test/Analysis/uninit-vals.m2
-rw-r--r--test/Analysis/unused-ivars.m2
-rw-r--r--test/CMakeLists.txt44
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.udir/p1.cpp35
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp24
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp67
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp141
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp44
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp2
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp2
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp4
-rw-r--r--test/CXX/expr/expr.unary/expr.delete/p5.cpp34
-rw-r--r--test/CXX/special/class.free/p1.cpp11
-rw-r--r--test/CXX/special/class.free/p6.cpp11
-rw-r--r--test/CXX/temp/temp.param/p1.cpp2
-rw-r--r--test/CXX/temp/temp.param/p12.cpp4
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp2
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp5
-rw-r--r--test/CodeCompletion/call.cpp5
-rw-r--r--test/CodeCompletion/enum-switch-case-qualified.cpp3
-rw-r--r--test/CodeCompletion/enum-switch-case.c3
-rw-r--r--test/CodeCompletion/enum-switch-case.cpp3
-rw-r--r--test/CodeCompletion/function-templates.cpp3
-rw-r--r--test/CodeCompletion/functions.cpp3
-rw-r--r--test/CodeCompletion/macros.c5
-rw-r--r--test/CodeCompletion/member-access.c3
-rw-r--r--test/CodeCompletion/member-access.cpp3
-rw-r--r--test/CodeCompletion/namespace-alias.cpp3
-rw-r--r--test/CodeCompletion/namespace.cpp3
-rw-r--r--test/CodeCompletion/nested-name-specifier.cpp3
-rw-r--r--test/CodeCompletion/objc-message.m35
-rw-r--r--test/CodeCompletion/operator.cpp3
-rw-r--r--test/CodeCompletion/ordinary-name.c3
-rw-r--r--test/CodeCompletion/property.m2
-rw-r--r--test/CodeCompletion/tag.c3
-rw-r--r--test/CodeCompletion/tag.cpp3
-rw-r--r--test/CodeCompletion/templates.cpp3
-rw-r--r--test/CodeCompletion/truncation.c5
-rw-r--r--test/CodeCompletion/using-namespace.cpp3
-rw-r--r--test/CodeCompletion/using.cpp3
-rw-r--r--test/CodeGen/2008-07-17-no-emit-on-error.c4
-rw-r--r--test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c2
-rw-r--r--test/CodeGen/2008-07-29-override-alias-decl.c18
-rw-r--r--test/CodeGen/2008-07-30-implicit-initialization.c4
-rw-r--r--test/CodeGen/2008-07-31-asm-labels.c14
-rw-r--r--test/CodeGen/2009-10-20-GlobalDebug.c2
-rw-r--r--test/CodeGen/PR2001-bitfield-reload.c4
-rw-r--r--test/CodeGen/PR3589-freestanding-libcalls.c6
-rw-r--r--test/CodeGen/PR3613-static-decl.c2
-rw-r--r--test/CodeGen/PR4611-bitfield-layout.c2
-rw-r--r--test/CodeGen/address-space-field1.c33
-rw-r--r--test/CodeGen/address-space.c8
-rw-r--r--test/CodeGen/alias.c12
-rw-r--r--test/CodeGen/alignof.c2
-rw-r--r--test/CodeGen/always_inline.c8
-rw-r--r--test/CodeGen/arm-arguments.c2
-rw-r--r--test/CodeGen/asm-2.c2
-rw-r--r--test/CodeGen/asm-inout.c2
-rw-r--r--test/CodeGen/asm.c6
-rw-r--r--test/CodeGen/atomic.c22
-rw-r--r--test/CodeGen/attr-nodebug.c2
-rw-r--r--test/CodeGen/attr-noinline.c2
-rw-r--r--test/CodeGen/attr-used.c6
-rw-r--r--test/CodeGen/attributes.c5
-rw-r--r--test/CodeGen/bitfield-assign.c10
-rw-r--r--test/CodeGen/bitfield-promote.c7
-rw-r--r--test/CodeGen/bitfield.c4
-rw-r--r--test/CodeGen/blocks-1.c16
-rw-r--r--test/CodeGen/blocks-2.c6
-rw-r--r--test/CodeGen/blocks-aligned-byref-variable.c2
-rw-r--r--test/CodeGen/blocks-seq.c12
-rw-r--r--test/CodeGen/blocks.c5
-rw-r--r--test/CodeGen/builtin-count-zeros.c2
-rw-r--r--test/CodeGen/builtin-memfns.c8
-rw-r--r--test/CodeGen/builtin-nanf.c2
-rw-r--r--test/CodeGen/builtin-stackaddress.c2
-rw-r--r--test/CodeGen/builtins-ffs_parity_popcount.c2
-rw-r--r--test/CodeGen/builtins-powi.c2
-rw-r--r--test/CodeGen/builtins-x86.c2
-rw-r--r--test/CodeGen/builtins.c4
-rw-r--r--test/CodeGen/c-strings.c8
-rw-r--r--test/CodeGen/cleanup-stack.c2
-rw-r--r--test/CodeGen/compound-type.c4
-rw-r--r--test/CodeGen/conditional.c8
-rw-r--r--test/CodeGen/const-init.c12
-rw-r--r--test/CodeGen/constant-comparison.c2
-rw-r--r--test/CodeGen/constructor-attribute.c10
-rw-r--r--test/CodeGen/darwin-string-literals.c2
-rw-r--r--test/CodeGen/debug-info.c2
-rw-r--r--test/CodeGen/designated-initializers.c4
-rw-r--r--test/CodeGen/dllimport-dllexport.c4
-rw-r--r--test/CodeGen/emit-all-decls.c6
-rw-r--r--test/CodeGen/ext-vector-shuffle.c4
-rw-r--r--test/CodeGen/flexible-array-init.c6
-rw-r--r--test/CodeGen/functions.c8
-rw-r--r--test/CodeGen/global-decls.c13
-rw-r--r--test/CodeGen/init.c4
-rw-r--r--test/CodeGen/inline.c74
-rw-r--r--test/CodeGen/inline2.c2
-rw-r--r--test/CodeGen/libcalls.c10
-rw-r--r--test/CodeGen/lineno-dbginfo.c6
-rw-r--r--test/CodeGen/mandel.c2
-rw-r--r--test/CodeGen/no-common.c6
-rw-r--r--test/CodeGen/object-size.c24
-rw-r--r--test/CodeGen/packed-union.c4
-rw-r--r--test/CodeGen/parameter-passing.c13
-rw-r--r--test/CodeGen/pragma-pack-2.c2
-rw-r--r--test/CodeGen/pragma-pack-3.c2
-rw-r--r--test/CodeGen/predefined-expr.c2
-rw-r--r--test/CodeGen/private-extern.c4
-rw-r--r--test/CodeGen/rdr-6098585-default-after-caserange.c4
-rw-r--r--test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c2
-rw-r--r--test/CodeGen/rdr-6098585-empty-case-range.c4
-rw-r--r--test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c2
-rw-r--r--test/CodeGen/rdr-6098585-unsigned-caserange.c4
-rw-r--r--test/CodeGen/stack-protector.c19
-rw-r--r--test/CodeGen/staticinit.c4
-rw-r--r--test/CodeGen/stdcall-fastcall.c2
-rw-r--r--test/CodeGen/string-init.c6
-rw-r--r--test/CodeGen/struct-passing.c15
-rw-r--r--test/CodeGen/struct-x86-darwin.c18
-rw-r--r--test/CodeGen/target-data.c13
-rw-r--r--test/CodeGen/tentative-decls.c15
-rw-r--r--test/CodeGen/trapv.c2
-rw-r--r--test/CodeGen/unreachable.c2
-rw-r--r--test/CodeGen/unwind-attr.c2
-rw-r--r--test/CodeGen/visibility.c49
-rw-r--r--test/CodeGen/volatile-1.c6
-rw-r--r--test/CodeGen/volatile.c4
-rw-r--r--test/CodeGen/x86.c16
-rw-r--r--test/CodeGen/x86_32-arguments.c111
-rw-r--r--test/CodeGen/x86_64-arguments.c51
-rw-r--r--test/CodeGenCXX/PR5050-constructor-conversion.cpp9
-rw-r--r--test/CodeGenCXX/array-construction.cpp9
-rw-r--r--test/CodeGenCXX/array-operator-delete-call.cpp63
-rw-r--r--test/CodeGenCXX/array-value-initialize.cpp28
-rw-r--r--test/CodeGenCXX/assign-operator.cpp9
-rw-r--r--test/CodeGenCXX/attr.cpp2
-rw-r--r--test/CodeGenCXX/call-arg-zero-temp.cpp9
-rw-r--r--test/CodeGenCXX/cast-conversion.cpp9
-rw-r--r--test/CodeGenCXX/class-layout.cpp2
-rw-r--r--test/CodeGenCXX/constructor-conversion.cpp9
-rw-r--r--test/CodeGenCXX/constructor-default-arg.cpp9
-rw-r--r--test/CodeGenCXX/constructor-for-array-members.cpp9
-rw-r--r--test/CodeGenCXX/constructor-template.cpp9
-rw-r--r--test/CodeGenCXX/conversion-function.cpp9
-rw-r--r--test/CodeGenCXX/convert-to-fptr.cpp9
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-1.cpp9
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis.cpp2
-rw-r--r--test/CodeGenCXX/copy-constructor-elim.cpp7
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis.cpp11
-rw-r--r--test/CodeGenCXX/debug-info.cpp13
-rw-r--r--test/CodeGenCXX/decl-ref-init.cpp9
-rw-r--r--test/CodeGenCXX/default-arg-temps.cpp6
-rw-r--r--test/CodeGenCXX/default-arguments.cpp13
-rw-r--r--test/CodeGenCXX/default-constructor-default-argument.cpp8
-rw-r--r--test/CodeGenCXX/default-constructor-for-members.cpp9
-rw-r--r--test/CodeGenCXX/default-destructor-synthesis.cpp9
-rw-r--r--test/CodeGenCXX/delete-two-arg.cpp6
-rw-r--r--test/CodeGenCXX/delete.cpp2
-rw-r--r--test/CodeGenCXX/derived-to-base-conv.cpp9
-rw-r--r--test/CodeGenCXX/destructors.cpp14
-rw-r--r--test/CodeGenCXX/dyncast.cpp414
-rw-r--r--test/CodeGenCXX/empty-union.cpp10
-rw-r--r--test/CodeGenCXX/explicit-instantiation.cpp2
-rw-r--r--test/CodeGenCXX/extern-c.cpp6
-rw-r--r--test/CodeGenCXX/global-array-destruction.cpp33
-rw-r--r--test/CodeGenCXX/implicit-instantiation-1.cpp11
-rw-r--r--test/CodeGenCXX/init-incomplete-type.cpp12
-rw-r--r--test/CodeGenCXX/instantiate-init-list.cpp13
-rw-r--r--test/CodeGenCXX/mangle-subst.cpp8
-rw-r--r--test/CodeGenCXX/mangle-system-header.cpp7
-rw-r--r--test/CodeGenCXX/mangle.cpp6
-rw-r--r--test/CodeGenCXX/member-expressions.cpp19
-rw-r--r--test/CodeGenCXX/member-function-pointers.cpp6
-rw-r--r--test/CodeGenCXX/member-functions.cpp20
-rw-r--r--test/CodeGenCXX/member-init-struct.cpp18
-rw-r--r--test/CodeGenCXX/member-init-union.cpp10
-rw-r--r--test/CodeGenCXX/member-pointers-zero-init.cpp16
-rw-r--r--test/CodeGenCXX/new-operator-phi.cpp11
-rw-r--r--test/CodeGenCXX/new.cpp3
-rw-r--r--test/CodeGenCXX/ptr-to-member-function.cpp9
-rw-r--r--test/CodeGenCXX/reinterpret-cast.cpp5
-rw-r--r--test/CodeGenCXX/rtti.cpp207
-rw-r--r--test/CodeGenCXX/static-init-1.cpp23
-rw-r--r--test/CodeGenCXX/static-init-2.cpp6
-rw-r--r--test/CodeGenCXX/static-init.cpp4
-rw-r--r--test/CodeGenCXX/temporaries.cpp87
-rw-r--r--test/CodeGenCXX/trivial-constructor-init.cpp5
-rw-r--r--test/CodeGenCXX/typeinfo16
-rw-r--r--test/CodeGenCXX/vararg-conversion-ctor.cpp23
-rw-r--r--test/CodeGenCXX/virt-dtor-gen.cpp10
-rw-r--r--test/CodeGenCXX/virt.cpp675
-rw-r--r--test/CodeGenCXX/virtual-operator-call.cpp10
-rw-r--r--test/CodeGenCXX/virtual-pseudo-destructor-call.cpp10
-rw-r--r--test/CodeGenCXX/x86_64-arguments.cpp7
-rw-r--r--test/CodeGenObjC/bitfield-1.m4
-rw-r--r--test/CodeGenObjC/bitfield-ivar-metadata.m2
-rw-r--r--test/CodeGenObjC/bitfield-ivar-offsets.m19
-rw-r--r--test/CodeGenObjC/blocks-1.m18
-rw-r--r--test/CodeGenObjC/blocks-2.m5
-rw-r--r--test/CodeGenObjC/blocks-3.m4
-rw-r--r--test/CodeGenObjC/blocks.m5
-rw-r--r--test/CodeGenObjC/category-super-class-meth.m2
-rw-r--r--test/CodeGenObjC/class-getter-dotsyntax.m2
-rw-r--r--test/CodeGenObjC/class-type.m4
-rw-r--r--test/CodeGenObjC/constant-strings.m4
-rw-r--r--test/CodeGenObjC/continuation-class.m2
-rw-r--r--test/CodeGenObjC/deadcode_strip_used_var.m6
-rw-r--r--test/CodeGenObjC/debug-info-linkagename.m2
-rw-r--r--test/CodeGenObjC/dot-syntax-1.m4
-rw-r--r--test/CodeGenObjC/dot-syntax.m4
-rw-r--r--test/CodeGenObjC/encode-test-1.m4
-rw-r--r--test/CodeGenObjC/encode-test-2.m10
-rw-r--r--test/CodeGenObjC/encode-test-3.m4
-rw-r--r--test/CodeGenObjC/encode-test-5.m10
-rw-r--r--test/CodeGenObjC/encode-test.m12
-rw-r--r--test/CodeGenObjC/forward-class-impl-metadata.m2
-rw-r--r--test/CodeGenObjC/hidden-visibility.m25
-rw-r--r--test/CodeGenObjC/hidden.m2
-rw-r--r--test/CodeGenObjC/image-info.m2
-rw-r--r--test/CodeGenObjC/implicit-objc_msgSend.m2
-rw-r--r--test/CodeGenObjC/interface-layout-64.m45
-rw-r--r--test/CodeGenObjC/interface.m2
-rw-r--r--test/CodeGenObjC/ivar-layout-64.m11
-rw-r--r--test/CodeGenObjC/ivar-layout-no-optimize.m5
-rw-r--r--test/CodeGenObjC/ivars.m2
-rw-r--r--test/CodeGenObjC/link-errors.m10
-rw-r--r--test/CodeGenObjC/message-arrays.m2
-rw-r--r--test/CodeGenObjC/messages-2.m4
-rw-r--r--test/CodeGenObjC/messages.m13
-rw-r--r--test/CodeGenObjC/metadata-symbols-32.m51
-rw-r--r--test/CodeGenObjC/metadata-symbols-64.m69
-rw-r--r--test/CodeGenObjC/metadata_symbols.m45
-rw-r--r--test/CodeGenObjC/missing-atend-metadata.m24
-rw-r--r--test/CodeGenObjC/newproperty-nested-synthesis-1.m2
-rw-r--r--test/CodeGenObjC/non-lazy-classes.m7
-rw-r--r--test/CodeGenObjC/objc-align.m21
-rw-r--r--test/CodeGenObjC/objc-assign-ivar.m5
-rw-r--r--test/CodeGenObjC/objc-gc-aggr-assign.m2
-rw-r--r--test/CodeGenObjC/objc-read-weak-byref.m9
-rw-r--r--test/CodeGenObjC/objc2-assign-global.m5
-rw-r--r--test/CodeGenObjC/objc2-ivar-assign.m5
-rw-r--r--test/CodeGenObjC/objc2-new-gc-api-strongcast.m5
-rw-r--r--test/CodeGenObjC/objc2-no-write-barrier.m2
-rw-r--r--test/CodeGenObjC/objc2-property-encode.m2
-rw-r--r--test/CodeGenObjC/objc2-protocol-enc.m8
-rw-r--r--test/CodeGenObjC/objc2-strong-cast.m2
-rw-r--r--test/CodeGenObjC/objc2-weak-assign.m2
-rw-r--r--test/CodeGenObjC/objc2-weak-compare.m2
-rw-r--r--test/CodeGenObjC/objc2-weak-import-attribute.m34
-rw-r--r--test/CodeGenObjC/objc2-weak-ivar-debug.m2
-rw-r--r--test/CodeGenObjC/objc2-write-barrier-2.m9
-rw-r--r--test/CodeGenObjC/objc2-write-barrier-3.m7
-rw-r--r--test/CodeGenObjC/objc2-write-barrier-4.m7
-rw-r--r--test/CodeGenObjC/objc2-write-barrier-5.m7
-rw-r--r--test/CodeGenObjC/objc2-write-barrier.m7
-rw-r--r--test/CodeGenObjC/object-incr-decr-1.m2
-rw-r--r--test/CodeGenObjC/overloadable.m4
-rw-r--r--test/CodeGenObjC/property-aggr-type.m2
-rw-r--r--test/CodeGenObjC/property-agrr-getter.m2
-rw-r--r--test/CodeGenObjC/property-complex.m2
-rw-r--r--test/CodeGenObjC/property-getter-dot-syntax.m2
-rw-r--r--test/CodeGenObjC/property-incr-decr-1.m2
-rw-r--r--test/CodeGenObjC/property-setter-attr.m2
-rw-r--r--test/CodeGenObjC/property.m4
-rw-r--r--test/CodeGenObjC/protocol-in-extended-class.m9
-rw-r--r--test/CodeGenObjC/protocol-property-synth.m2
-rw-r--r--test/CodeGenObjC/protocols-lazy.m27
-rw-r--r--test/CodeGenObjC/protocols.m2
-rw-r--r--test/CodeGenObjC/runtime-fns.m6
-rw-r--r--test/CodeGenObjC/super-classmethod-category.m2
-rw-r--r--test/CodeGenObjC/super-message-fragileabi.m32
-rw-r--r--test/CodeGenObjC/synchronized.m4
-rw-r--r--test/CodeGenObjC/synthesize_ivar-cont-class.m2
-rw-r--r--test/CodeGenObjC/synthesize_ivar.m2
-rw-r--r--test/CodeGenObjC/try.m2
-rw-r--r--test/CodeGenObjC/unname-bf-metadata.m2
-rw-r--r--test/CodeGenObjC/variadic-sends.m4
-rw-r--r--test/Coverage/ast-printing.c6
-rw-r--r--test/Coverage/ast-printing.cpp4
-rw-r--r--test/Coverage/ast-printing.m4
-rw-r--r--test/Coverage/codegen-next.m4
-rw-r--r--test/Coverage/codegen.c8
-rw-r--r--test/Coverage/html-diagnostics.c4
-rw-r--r--test/Coverage/parse-callbacks.c2
-rw-r--r--test/Coverage/parse-callbacks.m2
-rw-r--r--test/Coverage/targets.c39
-rw-r--r--test/Driver/Xarch.c17
-rw-r--r--test/Driver/analyze.c2
-rw-r--r--test/Driver/arm-darwin-builtin.c4
-rw-r--r--test/Driver/ast.c12
-rw-r--r--test/Driver/bindings.c97
-rw-r--r--test/Driver/clang-translation.c31
-rw-r--r--test/Driver/clang_cpp.c2
-rw-r--r--test/Driver/clang_f_opts.c21
-rw-r--r--test/Driver/cxx-pth.cpp8
-rw-r--r--test/Driver/darwin-as.c6
-rw-r--r--test/Driver/darwin-cc.c7
-rw-r--r--test/Driver/darwin-ld.c49
-rw-r--r--test/Driver/default-toolchain.c10
-rw-r--r--test/Driver/dragonfly.c2
-rw-r--r--test/Driver/emit-llvm.c2
-rw-r--r--test/Driver/flags.c10
-rw-r--r--test/Driver/freebsd.c4
-rw-r--r--test/Driver/hello.c6
-rw-r--r--test/Driver/immediate-options.c9
-rw-r--r--test/Driver/lto.c31
-rw-r--r--test/Driver/openbsd.c2
-rw-r--r--test/Driver/parsing.c35
-rw-r--r--test/Driver/phases.c25
-rw-r--r--test/Driver/preprocessor.c2
-rw-r--r--test/Driver/pth.c8
-rw-r--r--test/Driver/redzone.c6
-rw-r--r--test/Driver/std.c4
-rw-r--r--test/Driver/unknown-gcc-arch.c14
-rw-r--r--test/Driver/x86_features.c2
-rw-r--r--test/FixIt/fixit-at.c2
-rw-r--r--test/FixIt/fixit-c90.c2
-rw-r--r--test/FixIt/fixit-errors-1.c2
-rw-r--r--test/FixIt/fixit-errors.c12
-rw-r--r--test/FixIt/fixit-objc.m32
-rw-r--r--test/FixIt/fixit-pmem.cpp2
-rw-r--r--test/FixIt/fixit.c14
-rw-r--r--test/FixIt/fixit.cpp11
-rw-r--r--test/Frontend/ast-codegen.c2
-rw-r--r--test/Frontend/ast-main.c6
-rw-r--r--test/Frontend/cpp-output.c13
-rw-r--r--test/Frontend/darwin-version.c45
-rw-r--r--test/Frontend/dependency-gen.c10
-rw-r--r--test/Frontend/rewrite-macros.c11
-rw-r--r--test/Frontend/stdin.c2
-rw-r--r--test/Index/Inputs/c-index-pch.h7
-rw-r--r--test/Index/Inputs/foo.h8
-rw-r--r--test/Index/Inputs/lit.local.cfg1
-rw-r--r--test/Index/Inputs/objc.h11
-rw-r--r--test/Index/Inputs/t1.c28
-rw-r--r--test/Index/Inputs/t1.m20
-rw-r--r--test/Index/Inputs/t2.c11
-rw-r--r--test/Index/Inputs/t2.m13
-rw-r--r--test/Index/TestClassDecl.m52
-rw-r--r--test/Index/TestClassForwardDecl.m46
-rw-r--r--test/Index/c-index-api-loadTU-test.m224
-rw-r--r--test/Index/c-index-api-test.m2
-rw-r--r--test/Index/c-index-getCursor-test.m160
-rw-r--r--test/Index/c-index-pch.c8
-rw-r--r--test/Index/code-completion.cpp53
-rw-r--r--test/Index/comments.c18
-rw-r--r--test/Index/complete-member-access.m30
-rw-r--r--test/Index/complete-objc-message.m107
-rw-r--r--test/Index/complete-protocols.m25
-rw-r--r--test/Index/find-decls.c34
-rw-r--r--test/Index/find-defs.c26
-rw-r--r--test/Index/find-refs.c80
-rw-r--r--test/Index/multiple-redecls.c4
-rw-r--r--test/Index/objc-decls.m24
-rw-r--r--test/Index/objc-message.m60
-rw-r--r--test/Index/resolve-loc.c32
-rw-r--r--test/Lexer/block_cmt_end.c8
-rw-r--r--test/Lexer/counter.c8
-rw-r--r--test/Lexer/digraph.c2
-rw-r--r--test/Lexer/dollar-idents.c6
-rw-r--r--test/Lexer/escape_newline.c4
-rw-r--r--test/Lexer/rdr-6096838.c2
-rw-r--r--test/Lexer/token-concat.c2
-rw-r--r--test/Misc/caret-diags-macros.c14
-rw-r--r--test/Misc/diag-mapping.c16
-rw-r--r--test/Misc/diag-mapping2.c12
-rw-r--r--test/Misc/message-length.c2
-rw-r--r--test/PCH/asm.c4
-rw-r--r--test/PCH/attrs.c4
-rw-r--r--test/PCH/blocks.c4
-rw-r--r--test/PCH/builtins.c4
-rw-r--r--test/PCH/enum.c4
-rw-r--r--test/PCH/exprs.c4
-rw-r--r--test/PCH/ext_vector.c4
-rw-r--r--test/PCH/external-defs.c14
-rw-r--r--test/PCH/functions.c4
-rw-r--r--test/PCH/fuzzy-pch.c6
-rw-r--r--test/PCH/line-directive.c4
-rw-r--r--test/PCH/method_pool.m4
-rw-r--r--test/PCH/multiple_decls.c4
-rw-r--r--test/PCH/nonvisible-external-defs.c4
-rw-r--r--test/PCH/objc_exprs.m4
-rw-r--r--test/PCH/objc_import.m4
-rw-r--r--test/PCH/objc_methods.m4
-rw-r--r--test/PCH/objc_property.m4
-rw-r--r--test/PCH/pr4489.c4
-rw-r--r--test/PCH/preprocess.c11
-rw-r--r--test/PCH/reloc.c4
-rw-r--r--test/PCH/stmts.c4
-rw-r--r--test/PCH/struct.c4
-rw-r--r--test/PCH/tentative-defs.c6
-rw-r--r--test/PCH/types.c4
-rw-r--r--test/PCH/va_arg.c4
-rw-r--r--test/PCH/variables.c4
-rwxr-xr-xtest/Parser/2008-10-31-parse-noop-failure.c2
-rw-r--r--test/Parser/block-block-storageclass.c2
-rw-r--r--test/Parser/control-scope.c2
-rw-r--r--test/Parser/cxx-using-declaration.cpp4
-rw-r--r--test/Parser/objc-init.m18
-rw-r--r--test/Parser/objc-try-catch-1.m2
-rw-r--r--test/Preprocessor/_Pragma-dependency.c2
-rw-r--r--test/Preprocessor/_Pragma-physloc.c2
-rw-r--r--test/Preprocessor/assembler-with-cpp.c5
-rw-r--r--test/Preprocessor/builtin_line.c2
-rw-r--r--test/Preprocessor/comment_save_macro.c4
-rw-r--r--test/Preprocessor/cxx_and.cpp6
-rw-r--r--test/Preprocessor/cxx_bitand.cpp4
-rw-r--r--test/Preprocessor/cxx_bitor.cpp8
-rw-r--r--test/Preprocessor/cxx_compl.cpp4
-rw-r--r--test/Preprocessor/cxx_not.cpp2
-rw-r--r--test/Preprocessor/cxx_not_eq.cpp4
-rw-r--r--test/Preprocessor/cxx_oper_keyword.cpp2
-rw-r--r--test/Preprocessor/cxx_or.cpp6
-rw-r--r--test/Preprocessor/cxx_true.cpp4
-rw-r--r--test/Preprocessor/cxx_xor.cpp8
-rw-r--r--test/Preprocessor/dependencies-and-pp.c8
-rw-r--r--test/Preprocessor/dump-options.c2
-rw-r--r--test/Preprocessor/dump_macros.c16
-rw-r--r--test/Preprocessor/expr_comma.c2
-rw-r--r--test/Preprocessor/expr_invalid_tok.c4
-rw-r--r--test/Preprocessor/expr_liveness.c2
-rw-r--r--test/Preprocessor/feature_tests.c2
-rw-r--r--test/Preprocessor/hash_line.c4
-rw-r--r--test/Preprocessor/header_lookup1.c2
-rw-r--r--test/Preprocessor/if_warning.c2
-rw-r--r--test/Preprocessor/include-pth.c2
-rw-r--r--test/Preprocessor/init.c83
-rw-r--r--test/Preprocessor/line-directive.c4
-rw-r--r--test/Preprocessor/macro-multiline.c6
-rw-r--r--test/Preprocessor/macro_disable.c2
-rw-r--r--test/Preprocessor/macro_expand.c4
-rw-r--r--test/Preprocessor/macro_fn_comma_swallow.c6
-rw-r--r--test/Preprocessor/macro_fn_disable_expand.c2
-rw-r--r--test/Preprocessor/macro_fn_lparen_scan.c6
-rw-r--r--test/Preprocessor/macro_fn_preexpand.c2
-rw-r--r--test/Preprocessor/macro_fn_varargs_iso.c4
-rw-r--r--test/Preprocessor/macro_fn_varargs_named.c4
-rw-r--r--test/Preprocessor/macro_paste_c_block_comment.c4
-rw-r--r--test/Preprocessor/macro_paste_commaext.c8
-rw-r--r--test/Preprocessor/macro_paste_empty.c4
-rw-r--r--test/Preprocessor/macro_paste_hard.c4
-rw-r--r--test/Preprocessor/macro_rescan.c2
-rw-r--r--test/Preprocessor/macro_rescan2.c2
-rw-r--r--test/Preprocessor/objc-pp.m2
-rw-r--r--test/Preprocessor/optimize.c4
-rw-r--r--test/Preprocessor/pic.c19
-rw-r--r--test/Preprocessor/pragma_unknown.c2
-rw-r--r--test/Preprocessor/print_line_track.c8
-rw-r--r--test/Preprocessor/stdint.c593
-rw-r--r--test/Preprocessor/x86_target_features.c55
-rw-r--r--test/Rewriter/objc-ivar-receiver-1.m2
-rw-r--r--test/Sema/128bitint.c5
-rw-r--r--test/Sema/PR2727.c2
-rw-r--r--test/Sema/PR2728.c2
-rw-r--r--test/Sema/attr-format_arg.c2
-rw-r--r--test/Sema/attr-malloc.c6
-rw-r--r--test/Sema/block-byref-args.c2
-rw-r--r--test/Sema/block-storageclass.c2
-rw-r--r--test/Sema/builtin-object-size.c2
-rw-r--r--test/Sema/callingconv.c4
-rw-r--r--test/Sema/check-increment.c2
-rw-r--r--test/Sema/compare.c207
-rw-r--r--test/Sema/conditional-expr.c2
-rw-r--r--test/Sema/const-eval.c7
-rw-r--r--test/Sema/conversion-64-32.c5
-rw-r--r--test/Sema/conversion.c237
-rw-r--r--test/Sema/expr-comma-c89.c1
-rw-r--r--test/Sema/expr-comma.c1
-rw-r--r--test/Sema/format-attr-pr4470.c2
-rw-r--r--test/Sema/format-strings.c19
-rw-r--r--test/Sema/i-c-e.c2
-rw-r--r--test/Sema/implicit-builtin-redecl.c2
-rw-r--r--test/Sema/implicit-def.c2
-rw-r--r--test/Sema/parentheses.c2
-rw-r--r--test/Sema/pointer-conversion.c10
-rw-r--r--test/Sema/pragma-pack-4.c2
-rw-r--r--test/Sema/return.c2
-rw-r--r--test/Sema/shift.c2
-rw-r--r--test/Sema/ucn-cstring.c2
-rw-r--r--test/Sema/varargs.c2
-rw-r--r--test/Sema/wchar.c20
-rw-r--r--test/Sema/x86-intrinsics-headers.c4
-rw-r--r--test/SemaCXX/__null.cpp2
-rw-r--r--test/SemaCXX/arrow-operator.cpp7
-rw-r--r--test/SemaCXX/builtins.cpp7
-rw-r--r--test/SemaCXX/cast-conversion.cpp25
-rw-r--r--test/SemaCXX/compare.cpp204
-rw-r--r--test/SemaCXX/composite-pointer-type.cpp12
-rw-r--r--test/SemaCXX/conditional-expr.cpp2
-rw-r--r--test/SemaCXX/constructor-initializer.cpp26
-rw-r--r--test/SemaCXX/conversion-function.cpp30
-rw-r--r--test/SemaCXX/decltype-this.cpp3
-rw-r--r--test/SemaCXX/default-constructor-initializers.cpp16
-rw-r--r--test/SemaCXX/dependent-types.cpp2
-rw-r--r--test/SemaCXX/format-attribute.cpp8
-rw-r--r--test/SemaCXX/friend-class-nodecl.cpp2
-rw-r--r--test/SemaCXX/linkage-spec.cpp9
-rw-r--r--test/SemaCXX/member-expr.cpp3
-rw-r--r--test/SemaCXX/member-pointer-size.cpp2
-rw-r--r--test/SemaCXX/new-delete.cpp57
-rw-r--r--test/SemaCXX/overload-call.cpp13
-rw-r--r--test/SemaCXX/overloaded-builtin-operators.cpp13
-rw-r--r--test/SemaCXX/overloaded-operator.cpp9
-rw-r--r--test/SemaCXX/pseudo-destructors.cpp2
-rw-r--r--test/SemaCXX/static-cast.cpp42
-rw-r--r--test/SemaCXX/using-decl-1.cpp21
-rw-r--r--test/SemaCXX/using-decl-templates.cpp4
-rw-r--r--test/SemaCXX/value-initialization.cpp4
-rw-r--r--test/SemaCXX/vararg-default-arg.cpp10
-rw-r--r--test/SemaCXX/vararg-non-pod.cpp2
-rw-r--r--test/SemaCXX/warn-for-var-in-else.cpp14
-rw-r--r--test/SemaCXX/warn-unused-variables.cpp28
-rw-r--r--test/SemaObjC/atomoic-property-synnthesis-rules.m369
-rw-r--r--test/SemaObjC/call-super-2.m10
-rw-r--r--test/SemaObjC/class-method-lookup.m2
-rw-r--r--test/SemaObjC/compare-qualified-id.m5
-rw-r--r--test/SemaObjC/continuation-class-err.m2
-rw-r--r--test/SemaObjC/deref-interface.m2
-rw-r--r--test/SemaObjC/idiomatic-parentheses.m35
-rw-r--r--test/SemaObjC/ivar-sem-check-2.m2
-rw-r--r--test/SemaObjC/method-arg-decay.m5
-rw-r--r--test/SemaObjC/objc-string-constant.m2
-rw-r--r--test/SemaObjC/property-category-1.m1
-rw-r--r--test/SemaObjC/property-nonfragile-abi.m2
-rw-r--r--test/SemaObjC/sizeof-interface.m2
-rw-r--r--test/SemaObjC/static-ivar-ref-1.m2
-rw-r--r--test/SemaObjC/string.m2
-rw-r--r--test/SemaObjC/synthesized-ivar.m2
-rw-r--r--test/SemaObjC/unused.m5
-rw-r--r--test/SemaObjC/warn-selector-selection.m2
-rw-r--r--test/SemaTemplate/class-template-decl.cpp8
-rw-r--r--test/SemaTemplate/class-template-spec.cpp7
-rw-r--r--test/SemaTemplate/constructor-template.cpp32
-rw-r--r--test/SemaTemplate/deduction.cpp83
-rw-r--r--test/SemaTemplate/default-arguments.cpp81
-rw-r--r--test/SemaTemplate/default-expr-arguments.cpp40
-rw-r--r--test/SemaTemplate/enum-argument.cpp16
-rw-r--r--test/SemaTemplate/example-dynarray.cpp2
-rw-r--r--test/SemaTemplate/instantiate-attr.cpp7
-rw-r--r--test/SemaTemplate/instantiate-decl-init.cpp22
-rw-r--r--test/SemaTemplate/instantiate-member-pointers.cpp30
-rw-r--r--test/SemaTemplate/instantiate-member-template.cpp13
-rw-r--r--test/SemaTemplate/instantiate-overloaded-arrow.cpp20
-rw-r--r--test/SemaTemplate/instantiate-template-template-parm.cpp27
-rw-r--r--test/SemaTemplate/instantiate-using-decl.cpp3
-rw-r--r--test/SemaTemplate/instantiation-default-2.cpp2
-rw-r--r--test/SemaTemplate/member-function-template.cpp24
-rw-r--r--test/SemaTemplate/nested-name-spec-template.cpp17
-rw-r--r--test/SemaTemplate/nested-template.cpp18
-rw-r--r--test/SemaTemplate/operator-template.cpp2
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp3
-rw-r--r--test/SemaTemplate/temp_arg_template.cpp7
-rw-r--r--test/SemaTemplate/value-dependent-null-pointer-constant.cpp2
-rw-r--r--test/lit.cfg8
-rw-r--r--test/lit.site.cfg.in9
-rw-r--r--tools/CIndex/CIndex.cpp597
-rw-r--r--tools/CIndex/CIndex.exports9
-rw-r--r--tools/CIndex/CMakeLists.txt2
-rw-r--r--tools/CIndex/Makefile2
-rw-r--r--tools/CMakeLists.txt4
-rw-r--r--tools/c-index-test/c-index-test.c352
-rw-r--r--tools/clang-cc/CMakeLists.txt1
-rw-r--r--tools/clang-cc/Options.cpp1330
-rw-r--r--tools/clang-cc/Options.h57
-rw-r--r--tools/clang-cc/clang-cc.cpp2391
-rw-r--r--tools/driver/driver.cpp10
-rw-r--r--utils/C++Tests/Clang-Code-Compile/lit.local.cfg26
-rw-r--r--utils/C++Tests/Clang-Code-Syntax/lit.local.cfg25
-rw-r--r--utils/C++Tests/Clang-Syntax/lit.local.cfg23
-rw-r--r--utils/C++Tests/LLVM-Syntax/lit.local.cfg3
-rw-r--r--utils/C++Tests/lit.cfg12
-rwxr-xr-xutils/ccc-analyzer6
-rwxr-xr-xutils/scan-build8
-rw-r--r--www/get_started.html28
-rw-r--r--www/hacking.html64
918 files changed, 27114 insertions, 11704 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f4ab33b33a4..9e84d94a3b64 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -94,6 +94,11 @@ install(DIRECTORY include/
add_definitions( -D_GNU_SOURCE )
+option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF)
+if(CLANG_BUILD_EXAMPLES)
+ add_subdirectory(examples)
+endif ()
+
add_subdirectory(include)
add_subdirectory(lib)
add_subdirectory(tools)
diff --git a/Makefile b/Makefile
index 22fe214705cd..17ccc7320ec8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,12 @@
LEVEL = ../..
DIRS := include lib tools docs
+PARALLEL_DIRS :=
+
+ifeq ($(BUILD_EXAMPLES),1)
+ PARALLEL_DIRS += examples
+endif
+
include $(LEVEL)/Makefile.common
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
diff --git a/NOTES.txt b/NOTES.txt
index c658fe96bdfb..dc7a9bc0e754 100644
--- a/NOTES.txt
+++ b/NOTES.txt
@@ -50,7 +50,7 @@ TODO: File Manager Speedup:
//===---------------------------------------------------------------------===//
// Specifying targets: -triple and -arch
-===---------------------------------------------------------------------===//
+//===---------------------------------------------------------------------===//
The clang supports "-triple" and "-arch" options. At most one -triple and one
-arch option may be specified. Both are optional.
diff --git a/TODO.txt b/TODO.txt
index 522dcd37b365..7ceb0da15b36 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -66,3 +66,12 @@ More ideas for code modification hints:
- If a class member is defined out-of-line but isn't in the class declaration (and there are no close matches!), provide the option to add an in-class declaration.
- Fix-it hints for the inclusion of headers when needed for particular features (e.g., <typeinfo> for typeid)
- Change "foo.bar" to "foo->bar" when "foo" is a pointer.
+
+//===---------------------------------------------------------------------===//
+
+Options to support:
+ -Wfatal-errors
+ -ftabstop=width
+ -fpreprocessed mode.
+ -nostdinc++
+ -imultilib
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index 2b4aa04ca33c..f0a2194cb2c7 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -46,6 +46,9 @@
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
+ 1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795110A90C6100741BBA /* TypePrinter.cpp */; };
+ 1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795210A90C6100741BBA /* TypeLoc.cpp */; };
+ 1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795310A90C6100741BBA /* TemplateBase.cpp */; };
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
1AE4EE3E103B89ED00888A23 /* StmtProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */; };
1AE4EE40103B8A0A00888A23 /* TargetABIInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */; };
@@ -362,6 +365,7 @@
1A2A54B30FD1DD1C00F4CE45 /* StmtXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StmtXML.cpp; path = lib/Frontend/StmtXML.cpp; sourceTree = "<group>"; };
1A2A54B40FD1DD1C00F4CE45 /* Warnings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Warnings.cpp; path = lib/Frontend/Warnings.cpp; sourceTree = "<group>"; };
1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = "<group>"; tabWidth = 2; };
+ 1A31B27210ACE6DA009E0C8B /* GlobalDecl.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = GlobalDecl.h; path = lib/CodeGen/GlobalDecl.h; sourceTree = "<group>"; tabWidth = 2; };
1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ExprConstant.cpp; path = lib/AST/ExprConstant.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprConstant.cpp; path = lib/CodeGen/CGExprConstant.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A471AB40F437BC500753CE8 /* CGBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBlocks.cpp; path = lib/CodeGen/CGBlocks.cpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -396,6 +400,9 @@
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
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; };
+ 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>"; };
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiateDecl.cpp; path = lib/Sema/SemaTemplateInstantiateDecl.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TreeTransform.h; path = lib/Sema/TreeTransform.h; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -1289,6 +1296,7 @@
DE928B7E0C0A615600231DA4 /* CodeGenModule.cpp */,
DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */,
DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */,
+ 1A31B27210ACE6DA009E0C8B /* GlobalDecl.h */,
1A2193CC0F45EEB700C0713D /* Mangle.cpp */,
1A2193CD0F45EEB700C0713D /* Mangle.h */,
DE928B120C05659200231DA4 /* ModuleBuilder.cpp */,
@@ -1385,8 +1393,11 @@
DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */,
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */,
35CFFDFF0CA1CBCB00E6F2BE /* StmtViz.cpp */,
+ 1ADD795310A90C6100741BBA /* TemplateBase.cpp */,
DEDFF8870F848CF80035BD10 /* TemplateName.cpp */,
DE75EDF00B06880E0020CF81 /* Type.cpp */,
+ 1ADD795210A90C6100741BBA /* TypeLoc.cpp */,
+ 1ADD795110A90C6100741BBA /* TypePrinter.cpp */,
);
name = AST;
sourceTree = "<group>";
@@ -1919,6 +1930,9 @@
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */,
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */,
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */,
+ 1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */,
+ 1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */,
+ 1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/docs/UsersManual.html b/docs/UsersManual.html
index 20fdda72dced..cfaa071083bc 100644
--- a/docs/UsersManual.html
+++ b/docs/UsersManual.html
@@ -126,7 +126,7 @@ reasonably possible, easing migration from GCC to Clang. In most cases, code
<p>In addition to language specific features, Clang has a variety of features
that depend on what CPU architecture or operating system is being compiled for.
-Please see the <a href="target_features">Target-Specific Features and
+Please see the <a href="#target_features">Target-Specific Features and
Limitations</a> section for more details.</p>
<p>The rest of the introduction introduces some basic <a
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 1a58f44ff4c2..85f7a6a31bcb 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -115,6 +115,26 @@ typedef struct {
/* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */
typedef void *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.
+ */
+typedef struct {
+ const char *Spelling;
+ /* A 1 value indicates the clang_ indexing API needed to allocate the string
+ (and it must be freed by clang_disposeString()). */
+ int MustFreeString;
+} CXString;
+
+/* Get C string pointer from a CXString. */
+CINDEX_LINKAGE const char *clang_getCString(CXString string);
+
+/* Free CXString. */
+CINDEX_LINKAGE void clang_disposeString(CXString string);
+
/**
* \brief clang_createIndex() provides a shared context for creating
* translation units. It provides two options:
@@ -155,8 +175,7 @@ typedef void *CXEntity;
CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics);
CINDEX_LINKAGE void clang_disposeIndex(CXIndex);
-
-CINDEX_LINKAGE const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
+CINDEX_LINKAGE CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
/*
* \brief Create a translation unit from an AST file (-emit-ast).
@@ -260,7 +279,7 @@ CINDEX_LINKAGE CXEntity clang_getEntity(const char *URI);
*/
CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl);
-CINDEX_LINKAGE const char *clang_getDeclSpelling(CXDecl);
+CINDEX_LINKAGE CXString clang_getDeclSpelling(CXDecl);
CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
@@ -275,6 +294,8 @@ CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
*/
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
unsigned line, unsigned column);
+
+CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
@@ -282,9 +303,11 @@ CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind);
CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
+CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
+
CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor);
CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor);
-CINDEX_LINKAGE const char *clang_getCursorSpelling(CXCursor);
+CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */
CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor);
@@ -305,6 +328,328 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
*/
CINDEX_LINKAGE CXDecl clang_getCursorDecl(CXCursor);
+/**
+ * \brief A semantic string that describes a code-completion result.
+ *
+ * A semantic string that describes the formatting of a code-completion
+ * result as a single "template" of text that should be inserted into the
+ * source buffer when a particular code-completion result is selected.
+ * Each semantic string is made up of some number of "chunks", each of which
+ * contains some text along with a description of what that text means, e.g.,
+ * the name of the entity being referenced, whether the text chunk is part of
+ * the template, or whether it is a "placeholder" that the user should replace
+ * with actual code,of a specific kind. See \c CXCompletionChunkKind for a
+ * description of the different kinds of chunks.
+ */
+typedef void *CXCompletionString;
+
+/**
+ * \brief A single result of code completion.
+ */
+typedef struct {
+ /**
+ * \brief The kind of entity that this completion refers to.
+ *
+ * The cursor kind will be a macro, keyword, or a declaration (one of the
+ * *Decl cursor kinds), describing the entity that the completion is
+ * referring to.
+ *
+ * \todo In the future, we would like to provide a full cursor, to allow
+ * the client to extract additional information from declaration.
+ */
+ enum CXCursorKind CursorKind;
+
+ /**
+ * \brief The code-completion string that describes how to insert this
+ * code-completion result into the editing buffer.
+ */
+ CXCompletionString CompletionString;
+} CXCompletionResult;
+
+/**
+ * \brief Describes a single piece of text within a code-completion string.
+ *
+ * Each "chunk" within a code-completion string (\c CXCompletionString) is
+ * either a piece of text with a specific "kind" that describes how that text
+ * should be interpreted by the client or is another completion string.
+ */
+enum CXCompletionChunkKind {
+ /**
+ * \brief A code-completion string that describes "optional" text that
+ * could be a part of the template (but is not required).
+ *
+ * The Optional chunk is the only kind of chunk that has a code-completion
+ * string for its representation, which is accessible via
+ * \c clang_getCompletionChunkCompletionString(). The code-completion string
+ * describes an additional part of the template that is completely optional.
+ * For example, optional chunks can be used to describe the placeholders for
+ * arguments that match up with defaulted function parameters, e.g. given:
+ *
+ * \code
+ * void f(int x, float y = 3.14, double z = 2.71828);
+ * \endcode
+ *
+ * The code-completion string for this function would contain:
+ * - a TypedText chunk for "f".
+ * - a LeftParen chunk for "(".
+ * - a Placeholder chunk for "int x"
+ * - an Optional chunk containing the remaining defaulted arguments, e.g.,
+ * - a Comma chunk for ","
+ * - a Placeholder chunk for "float x"
+ * - an Optional chunk containing the last defaulted argument:
+ * - a Comma chunk for ","
+ * - a Placeholder chunk for "double z"
+ * - a RightParen chunk for ")"
+ *
+ * There are many ways two handle Optional chunks. Two simple approaches are:
+ * - Completely ignore optional chunks, in which case the template for the
+ * function "f" would only include the first parameter ("int x").
+ * - Fully expand all optional chunks, in which case the template for the
+ * function "f" would have all of the parameters.
+ */
+ CXCompletionChunk_Optional,
+ /**
+ * \brief Text that a user would be expected to type to get this
+ * code-completion result.
+ *
+ * There will be exactly one "typed text" chunk in a semantic string, which
+ * will typically provide the spelling of a keyword or the name of a
+ * declaration that could be used at the current code point. Clients are
+ * expected to filter the code-completion results based on the text in this
+ * chunk.
+ */
+ CXCompletionChunk_TypedText,
+ /**
+ * \brief Text that should be inserted as part of a code-completion result.
+ *
+ * A "text" chunk represents text that is part of the template to be
+ * inserted into user code should this particular code-completion result
+ * be selected.
+ */
+ CXCompletionChunk_Text,
+ /**
+ * \brief Placeholder text that should be replaced by the user.
+ *
+ * A "placeholder" chunk marks a place where the user should insert text
+ * into the code-completion template. For example, placeholders might mark
+ * the function parameters for a function declaration, to indicate that the
+ * user should provide arguments for each of those parameters. The actual
+ * text in a placeholder is a suggestion for the text to display before
+ * the user replaces the placeholder with real code.
+ */
+ CXCompletionChunk_Placeholder,
+ /**
+ * \brief Informative text that should be displayed but never inserted as
+ * part of the template.
+ *
+ * An "informative" chunk contains annotations that can be displayed to
+ * help the user decide whether a particular code-completion result is the
+ * right option, but which is not part of the actual template to be inserted
+ * by code completion.
+ */
+ CXCompletionChunk_Informative,
+ /**
+ * \brief Text that describes the current parameter when code-completion is
+ * referring to function call, message send, or template specialization.
+ *
+ * A "current parameter" chunk occurs when code-completion is providing
+ * information about a parameter corresponding to the argument at the
+ * code-completion point. For example, given a function
+ *
+ * \code
+ * int add(int x, int y);
+ * \endcode
+ *
+ * and the source code \c add(, where the code-completion point is after the
+ * "(", the code-completion string will contain a "current parameter" chunk
+ * for "int x", indicating that the current argument will initialize that
+ * parameter. After typing further, to \c add(17, (where the code-completion
+ * point is after the ","), the code-completion string will contain a
+ * "current paremeter" chunk to "int y".
+ */
+ CXCompletionChunk_CurrentParameter,
+ /**
+ * \brief A left parenthesis ('('), used to initiate a function call or
+ * signal the beginning of a function parameter list.
+ */
+ CXCompletionChunk_LeftParen,
+ /**
+ * \brief A right parenthesis (')'), used to finish a function call or
+ * signal the end of a function parameter list.
+ */
+ CXCompletionChunk_RightParen,
+ /**
+ * \brief A left bracket ('[').
+ */
+ CXCompletionChunk_LeftBracket,
+ /**
+ * \brief A right bracket (']').
+ */
+ CXCompletionChunk_RightBracket,
+ /**
+ * \brief A left brace ('{').
+ */
+ CXCompletionChunk_LeftBrace,
+ /**
+ * \brief A right brace ('}').
+ */
+ CXCompletionChunk_RightBrace,
+ /**
+ * \brief A left angle bracket ('<').
+ */
+ CXCompletionChunk_LeftAngle,
+ /**
+ * \brief A right angle bracket ('>').
+ */
+ CXCompletionChunk_RightAngle,
+ /**
+ * \brief A comma separator (',').
+ */
+ CXCompletionChunk_Comma
+};
+
+/**
+ * \brief Callback function that receives a single code-completion result.
+ *
+ * This callback will be invoked by \c clang_codeComplete() for each
+ * code-completion result.
+ *
+ * \param completion_result a pointer to the current code-completion result,
+ * providing one possible completion. The pointer itself is only valid
+ * during the execution of the completion callback.
+ *
+ * \param client_data the client data provided to \c clang_codeComplete().
+ */
+typedef void (*CXCompletionIterator)(CXCompletionResult *completion_result,
+ CXClientData client_data);
+
+/**
+ * \brief Determine the kind of a particular chunk within a completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the kind of the chunk at the index \c chunk_number.
+ */
+CINDEX_LINKAGE enum CXCompletionChunkKind
+clang_getCompletionChunkKind(CXCompletionString completion_string,
+ unsigned chunk_number);
+
+/**
+ * \brief Retrieve the text associated with a particular chunk within a
+ * completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the text associated with the chunk at index \c chunk_number.
+ */
+CINDEX_LINKAGE const char *
+clang_getCompletionChunkText(CXCompletionString completion_string,
+ unsigned chunk_number);
+
+/**
+ * \brief Retrieve the completion string associated with a particular chunk
+ * within a completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the completion string associated with the chunk at index
+ * \c chunk_number, or NULL if that chunk is not represented by a completion
+ * string.
+ */
+CINDEX_LINKAGE CXCompletionString
+clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
+ unsigned chunk_number);
+
+/**
+ * \brief Retrieve the number of chunks in the given code-completion string.
+ */
+CINDEX_LINKAGE unsigned
+clang_getNumCompletionChunks(CXCompletionString completion_string);
+
+/**
+ * \brief Perform code completion at a given location in a source file.
+ *
+ * This function performs code completion at a particular file, line, and
+ * column within source code, providing results that suggest potential
+ * code snippets based on the context of the completion. The basic model
+ * for code completion is that Clang will parse a complete source file,
+ * performing syntax checking up to the location where code-completion has
+ * been requested. At that point, a special code-completion token is passed
+ * to the parser, which recognizes this token and determines, based on the
+ * current location in the C/Objective-C/C++ grammar and the state of
+ * semantic analysis, what completions to provide. These completions are
+ * enumerated through a callback interface to the client.
+ *
+ * Code completion itself is meant to be triggered by the client when the
+ * user types punctuation characters or whitespace, at which point the
+ * code-completion location will coincide with the cursor. For example, if \c p
+ * is a pointer, code-completion might be triggered after the "-" and then
+ * after the ">" in \c p->. When the code-completion location is afer the ">",
+ * the completion results will provide, e.g., the members of the struct that
+ * "p" points to. The client is responsible for placing the cursor at the
+ * beginning of the token currently being typed, then filtering the results
+ * based on the contents of the token. For example, when code-completing for
+ * the expression \c p->get, the client should provide the location just after
+ * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the
+ * client can filter the results based on the current token text ("get"), only
+ * showing those results that start with "get". The intent of this interface
+ * is to separate the relatively high-latency acquisition of code-competion
+ * results from the filtering of results on a per-character basis, which must
+ * have a lower latency.
+ *
+ * \param CIdx the \c CXIndex instance that will be used to perform code
+ * completion.
+ *
+ * \param source_filename the name of the source file that should be parsed
+ * to perform code-completion. This source file must be the same as or
+ * include the filename described by \p complete_filename, or no code-completion
+ * results will be produced. NOTE: One can also specify NULL for this argument if
+ * the source file is included in command_line_args.
+ *
+ * \param num_command_line_args the number of command-line arguments stored in
+ * \p command_line_args.
+ *
+ * \param command_line_args the command-line arguments to pass to the Clang
+ * compiler to build the given source file. This should include all of the
+ * necessary include paths, language-dialect switches, precompiled header
+ * includes, etc., but should not include any information specific to
+ * code completion.
+ *
+ * \param complete_filename the name of the source file where code completion
+ * should be performed. In many cases, this name will be the same as the
+ * source filename. However, the completion filename may also be a file
+ * included by the source file, which is required when producing
+ * code-completion results for a header.
+ *
+ * \param complete_line the line at which code-completion should occur.
+ *
+ * \param complete_column the column at which code-completion should occur.
+ * Note that the column should point just after the syntactic construct that
+ * initiated code completion, and not in the middle of a lexical token.
+ *
+ * \param completion_iterator a callback function that will receive
+ * code-completion results.
+ *
+ * \param client_data client-specific data that will be passed back via the
+ * code-completion callback function.
+ */
+CINDEX_LINKAGE void clang_codeComplete(CXIndex CIdx,
+ const char *source_filename,
+ int num_command_line_args,
+ const char **command_line_args,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column,
+ CXCompletionIterator completion_iterator,
+ CXClientData client_data);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 7392170be995..f9d2f71b1f28 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -37,6 +37,7 @@ namespace llvm {
namespace clang {
class FileManager;
class ASTRecordLayout;
+ class BlockExpr;
class Expr;
class ExternalASTSource;
class IdentifierTable;
@@ -55,7 +56,6 @@ namespace clang {
class TranslationUnitDecl;
class TypeDecl;
class TypedefDecl;
- class UnresolvedUsingDecl;
class UsingDecl;
namespace Builtin { class Context; }
@@ -204,7 +204,7 @@ class ASTContext {
///
/// This mapping will contain an entry that maps from the UsingDecl in
/// B<int> to the UnresolvedUsingDecl in B<T>.
- llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>
+ llvm::DenseMap<UsingDecl *, NamedDecl *>
InstantiatedFromUnresolvedUsingDecl;
llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
@@ -232,7 +232,7 @@ class ASTContext {
llvm::DenseMap<const Decl *, std::string> DeclComments;
public:
- TargetInfo &Target;
+ const TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
@@ -284,12 +284,11 @@ public:
/// \brief If this using decl is instantiated from an unresolved using decl,
/// return it.
- UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
+ NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
/// \brief Note that the using decl \p Inst is an instantiation of
/// the unresolved using decl \p Tmpl of a class template.
- void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst,
- UnresolvedUsingDecl *Tmpl);
+ void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl);
FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);
@@ -319,7 +318,7 @@ public:
CanQualType UndeducedAutoTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
- ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
+ ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
bool FreeMemory = true, unsigned size_reserve=0);
@@ -672,6 +671,10 @@ public:
/// declaration.
void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S);
+ /// getObjCEncodingForBlockDecl - Return the encoded type for this block
+ /// declaration.
+ void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S);
+
/// getObjCEncodingForPropertyDecl - Return the encoded type for
/// this method declaration. If non-NULL, Container must be either
/// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should
@@ -872,9 +875,9 @@ public:
/// \brief Determine whether the given types are equivalent after
/// cvr-qualifiers have been removed.
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
- T1 = getCanonicalType(T1);
- T2 = getCanonicalType(T2);
- return T1.getUnqualifiedType() == T2.getUnqualifiedType();
+ CanQualType CT1 = getCanonicalType(T1);
+ CanQualType CT2 = getCanonicalType(T2);
+ return CT1.getUnqualifiedType() == CT2.getUnqualifiedType();
}
/// \brief Retrieves the "canonical" declaration of
@@ -925,6 +928,10 @@ public:
/// types, values, and templates.
TemplateName getCanonicalTemplateName(TemplateName Name);
+ /// \brief Determine whether the given template names refer to the same
+ /// template.
+ bool hasSameTemplateName(TemplateName X, TemplateName Y);
+
/// \brief Retrieve the "canonical" template argument.
///
/// The canonical template argument is the simplest template argument
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index f7a47364a7f6..b36ff1229376 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -50,6 +50,7 @@ public:
Annotate,
AsmLabel, // Represent GCC asm label extension.
Blocks,
+ CDecl,
Cleanup,
Const,
Constructor,
@@ -442,6 +443,7 @@ DEF_SIMPLE_ATTR(DLLImport);
DEF_SIMPLE_ATTR(DLLExport);
DEF_SIMPLE_ATTR(FastCall);
DEF_SIMPLE_ATTR(StdCall);
+DEF_SIMPLE_ATTR(CDecl);
DEF_SIMPLE_ATTR(TransparentUnion);
DEF_SIMPLE_ATTR(ObjCNSObject);
DEF_SIMPLE_ATTR(ObjCException);
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index a7750517090e..9b1187770f6a 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -71,6 +71,9 @@ public:
/// \brief Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
+ /// \brief Implicit conversion to bool.
+ operator bool() const { return !isNull(); }
+
bool isNull() const {
return Stored.isNull();
}
@@ -99,22 +102,22 @@ public:
CanProxy<T> operator->() const;
/// \brief Retrieve all qualifiers.
- Qualifiers getQualifiers() const { return Stored.getQualifiers(); }
+ Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
/// \brief Retrieve the const/volatile/restrict qualifiers.
- unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); }
+ unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
/// \brief Determines whether this type has any qualifiers
- bool hasQualifiers() const { return Stored.hasQualifiers(); }
+ bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
bool isConstQualified() const {
- return Stored.isConstQualified();
+ return Stored.isLocalConstQualified();
}
bool isVolatileQualified() const {
- return Stored.isVolatileQualified();
+ return Stored.isLocalVolatileQualified();
}
bool isRestrictQualified() const {
- return Stored.isRestrictQualified();
+ return Stored.isLocalRestrictQualified();
}
/// \brief Retrieve the unqualified form of this type.
@@ -635,7 +638,7 @@ struct CanProxyAdaptor<ObjCObjectPointerType>
//----------------------------------------------------------------------------//
template<typename T>
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
- return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType());
+ return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
}
template<typename T>
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 813e83accdb1..ac79a91792d7 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -232,6 +232,7 @@ public:
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; }
+ const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; }
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), RBracLoc);
@@ -552,6 +553,9 @@ public:
}
virtual VarDecl *getCanonicalDecl();
+ const VarDecl *getCanonicalDecl() const {
+ return const_cast<VarDecl*>(this)->getCanonicalDecl();
+ }
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
@@ -1424,6 +1428,9 @@ public:
virtual SourceRange getSourceRange() const;
virtual TagDecl* getCanonicalDecl();
+ const TagDecl* getCanonicalDecl() const {
+ return const_cast<TagDecl*>(this)->getCanonicalDecl();
+ }
/// isDefinition - Return true if this decl has its body specified.
bool isDefinition() const {
@@ -1515,6 +1522,9 @@ public:
EnumDecl *getCanonicalDecl() {
return cast<EnumDecl>(TagDecl::getCanonicalDecl());
}
+ const EnumDecl *getCanonicalDecl() const {
+ return cast<EnumDecl>(TagDecl::getCanonicalDecl());
+ }
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 10db7030db18..79f766356138 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -79,9 +79,11 @@ public:
/// namespaces, labels, tags, members and ordinary
/// identifiers. These are meant as bitmasks, so that searches in
/// C++ can look into the "tag" namespace during ordinary lookup. We
- /// use additional namespaces for Objective-C entities. We also
- /// put C++ friend declarations (of previously-undeclared entities) in
- /// shadow namespaces.
+ /// use additional namespaces for Objective-C entities. We also put
+ /// C++ friend declarations (of previously-undeclared entities) in
+ /// shadow namespaces, and 'using' declarations (as opposed to their
+ /// implicit shadow declarations) can be found in their own
+ /// namespace.
enum IdentifierNamespace {
IDNS_Label = 0x1,
IDNS_Tag = 0x2,
@@ -91,7 +93,8 @@ public:
IDNS_ObjCImplementation = 0x20,
IDNS_ObjCCategoryImpl = 0x40,
IDNS_OrdinaryFriend = 0x80,
- IDNS_TagFriend = 0x100
+ IDNS_TagFriend = 0x100,
+ IDNS_Using = 0x200
};
/// ObjCDeclQualifier - Qualifier used on types in method declarations
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index c858c5c0df78..e5bf78cd10d2 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -432,6 +432,9 @@ public:
virtual CXXRecordDecl *getCanonicalDecl() {
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
}
+ virtual const CXXRecordDecl *getCanonicalDecl() const {
+ return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+ }
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -768,7 +771,7 @@ public:
/// \param Base the base class we are searching for.
///
/// \returns true if this class is derived from Base, false otherwise.
- bool isDerivedFrom(CXXRecordDecl *Base);
+ bool isDerivedFrom(CXXRecordDecl *Base) const;
/// \brief Determine whether this class is derived from the type \p Base.
///
@@ -786,7 +789,7 @@ public:
///
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
/// tangling input and output in \p Paths
- bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths);
+ bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
/// \brief Function type used by lookupInBases() to determine whether a
/// specific base class subobject matches the lookup criteria.
@@ -801,7 +804,7 @@ public:
/// lookupInBases().
///
/// \returns true if this base matched the search criteria, false otherwise.
- typedef bool BaseMatchesCallback(CXXBaseSpecifier *Specifier,
+ typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *UserData);
@@ -826,7 +829,7 @@ public:
/// \returns true if there exists any path from this class to a base class
/// subobject that matches the search criteria.
bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
- CXXBasePaths &Paths);
+ CXXBasePaths &Paths) const;
/// \brief Base-class lookup callback that determines whether the given
/// base class specifier refers to a specific class declaration.
@@ -835,8 +838,8 @@ public:
/// a given derived class has is a base class subobject of a particular type.
/// The user data pointer should refer to the canonical CXXRecordDecl of the
/// base class that we are searching for.
- static bool FindBaseClass(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
- void *BaseRecord);
+ static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *BaseRecord);
/// \brief Base-class lookup callback that determines whether there exists
/// a tag with the given name.
@@ -844,8 +847,8 @@ public:
/// This callback can be used with \c lookupInBases() to find tag members
/// of the given name within a C++ class hierarchy. The user data pointer
/// is an opaque \c DeclarationName pointer.
- static bool FindTagMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
- void *Name);
+ static bool FindTagMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name.
@@ -853,8 +856,8 @@ public:
/// This callback can be used with \c lookupInBases() to find members
/// of the given name within a C++ class hierarchy. The user data pointer
/// is an opaque \c DeclarationName pointer.
- static bool FindOrdinaryMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
- void *Name);
+ static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name that can be used in a nested-name-specifier.
@@ -862,7 +865,7 @@ public:
/// This callback can be used with \c lookupInBases() to find membes of
/// the given name within a C++ class hierarchy that can occur within
/// nested-name-specifiers.
- static bool FindNestedNameSpecifierMember(CXXBaseSpecifier *Specifier,
+ static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *UserData);
@@ -1244,6 +1247,11 @@ public:
/// used for user-defined conversions.
bool isConvertingConstructor(bool AllowExplicit) const;
+ /// \brief Determine whether this is a member template specialization that
+ /// looks like a copy constructor. Such constructors are never used to copy
+ /// an object.
+ bool isCopyConstructorLikeSpecialization() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == CXXConstructor;
@@ -1261,13 +1269,6 @@ public:
/// };
/// @endcode
class CXXDestructorDecl : public CXXMethodDecl {
-public:
- enum KindOfObjectToDestroy {
- VBASE = 0x1,
- DRCTNONVBASE = 0x2,
- ANYBASE = 0x3
- };
-private:
/// ImplicitlyDefined - Whether this destructor was implicitly
/// defined by the compiler. When false, the destructor was defined
/// by the user. In C++03, this flag will have the same value as
@@ -1276,24 +1277,15 @@ private:
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
- /// Support for base and member destruction.
- /// BaseOrMemberDestructions - The arguments used to destruct the base
- /// or member. Each uintptr_t value represents one of base classes (either
- /// virtual or direct non-virtual base), or non-static data member
- /// to be destroyed. The low two bits encode the kind of object
- /// being destroyed.
- uintptr_t *BaseOrMemberDestructions;
- unsigned NumBaseOrMemberDestructions;
-
+ FunctionDecl *OperatorDelete;
+
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline),
- ImplicitlyDefined(false),
- BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0) {
+ ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
}
- virtual void Destroy(ASTContext& C);
public:
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
@@ -1319,95 +1311,8 @@ public:
ImplicitlyDefined = ID;
}
- /// destr_iterator - Iterates through the member/base destruction list.
-
- /// destr_const_iterator - Iterates through the member/base destruction list.
- typedef uintptr_t const destr_const_iterator;
-
- /// destr_begin() - Retrieve an iterator to the first destructed member/base.
- uintptr_t* destr_begin() {
- return BaseOrMemberDestructions;
- }
- /// destr_begin() - Retrieve an iterator to the first destructed member/base.
- uintptr_t* destr_begin() const {
- return BaseOrMemberDestructions;
- }
-
- /// destr_end() - Retrieve an iterator past the last destructed member/base.
- uintptr_t* destr_end() {
- return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
- }
- /// destr_end() - Retrieve an iterator past the last destructed member/base.
- uintptr_t* destr_end() const {
- return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
- }
-
- /// getNumBaseOrMemberDestructions - Number of base and non-static members
- /// to destroy.
- unsigned getNumBaseOrMemberDestructions() const {
- return NumBaseOrMemberDestructions;
- }
-
- /// setNumBaseOrMemberDestructions - Set number of base and non-static members
- /// to destroy.
- void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) {
- NumBaseOrMemberDestructions = numBaseOrMemberDestructions;
- }
-
- /// getBaseOrMemberToDestroy - get the generic 'member' representing either
- /// the field or a base class.
- uintptr_t* getBaseOrMemberToDestroy() const {
- return BaseOrMemberDestructions;
- }
-
- /// setBaseOrMemberToDestroy - set the generic 'member' representing either
- /// the field or a base class.
- void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) {
- BaseOrMemberDestructions = baseOrMemberDestructions;
- }
-
- /// isVbaseToDestroy - returns true, if object is virtual base.
- bool isVbaseToDestroy(uintptr_t Vbase) const {
- return (Vbase & VBASE) != 0;
- }
- /// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual
- /// base.
- bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const {
- return (DrctNonVbase & DRCTNONVBASE) != 0;
- }
- /// isAnyBaseToDestroy - returns true, if object is any base (virtual or
- /// direct non-virtual)
- bool isAnyBaseToDestroy(uintptr_t AnyBase) const {
- return (AnyBase & ANYBASE) != 0;
- }
- /// isMemberToDestroy - returns true if object is a non-static data member.
- bool isMemberToDestroy(uintptr_t Member) const {
- return (Member & ANYBASE) == 0;
- }
- /// getAnyBaseClassToDestroy - Get the type for the given base class object.
- Type *getAnyBaseClassToDestroy(uintptr_t Base) const {
- if (isAnyBaseToDestroy(Base))
- return reinterpret_cast<Type*>(Base & ~0x03);
- return 0;
- }
- /// getMemberToDestroy - Get the member for the given object.
- FieldDecl *getMemberToDestroy(uintptr_t Member) const {
- if (isMemberToDestroy(Member))
- return reinterpret_cast<FieldDecl *>(Member);
- return 0;
- }
- /// getVbaseClassToDestroy - Get the virtual base.
- Type *getVbaseClassToDestroy(uintptr_t Vbase) const {
- if (isVbaseToDestroy(Vbase))
- return reinterpret_cast<Type*>(Vbase & ~0x01);
- return 0;
- }
- /// getDirectNonVBaseClassToDestroy - Get the virtual base.
- Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const {
- if (isDirectNonVBaseToDestroy(Base))
- return reinterpret_cast<Type*>(Base & ~0x02);
- return 0;
- }
+ void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
+ const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
@@ -1739,6 +1644,56 @@ public:
static bool classof(const NamespaceAliasDecl *D) { return true; }
};
+/// UsingShadowDecl - Represents a shadow declaration introduced into
+/// a scope by a (resolved) using declaration. For example,
+///
+/// namespace A {
+/// void foo();
+/// }
+/// namespace B {
+/// using A::foo(); // <- a UsingDecl
+/// // Also creates a UsingShadowDecl for A::foo in B
+/// }
+///
+class UsingShadowDecl : public NamedDecl {
+ /// The referenced declaration.
+ NamedDecl *Underlying;
+
+ /// The using declaration which introduced this decl.
+ UsingDecl *Using;
+
+ UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target)
+ : NamedDecl(UsingShadow, DC, Loc, Target->getDeclName()),
+ Underlying(Target), Using(Using) {
+ IdentifierNamespace = Target->getIdentifierNamespace();
+ setImplicit();
+ }
+
+public:
+ static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target) {
+ return new (C) UsingShadowDecl(DC, Loc, Using, Target);
+ }
+
+ /// Gets the underlying declaration which has been brought into the
+ /// local scope.
+ NamedDecl *getTargetDecl() const {
+ return Underlying;
+ }
+
+ /// Gets the using declaration to which this declaration is tied.
+ UsingDecl *getUsingDecl() const {
+ return Using;
+ }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::UsingShadow;
+ }
+ static bool classof(const UsingShadowDecl *D) { return true; }
+};
+
/// UsingDecl - Represents a C++ using-declaration. For example:
/// using someNameSpace::someIdentifier;
class UsingDecl : public NamedDecl {
@@ -1746,29 +1701,26 @@ class UsingDecl : public NamedDecl {
/// preceding the declaration name.
SourceRange NestedNameRange;
- /// \brief The source location of the target declaration name.
- SourceLocation TargetNameLocation;
-
/// \brief The source location of the "using" location itself.
SourceLocation UsingLocation;
- /// \brief Target declaration.
- NamedDecl* TargetDecl;
-
/// \brief Target nested name specifier.
- NestedNameSpecifier* TargetNestedNameDecl;
+ NestedNameSpecifier* TargetNestedName;
+
+ /// \brief The collection of shadow declarations associated with
+ /// this using declaration. This set can change as a class is
+ /// processed.
+ llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows;
// \brief Has 'typename' keyword.
bool IsTypeName;
UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
- SourceLocation TargetNL, SourceLocation UL, NamedDecl* Target,
- NestedNameSpecifier* TargetNNS, bool IsTypeNameArg)
- : NamedDecl(Decl::Using, DC, L, Target->getDeclName()),
- NestedNameRange(NNR), TargetNameLocation(TargetNL),
- UsingLocation(UL), TargetDecl(Target),
- TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) {
- this->IdentifierNamespace = TargetDecl->getIdentifierNamespace();
+ SourceLocation UL, NestedNameSpecifier* TargetNNS,
+ DeclarationName Name, bool IsTypeNameArg)
+ : NamedDecl(Decl::Using, DC, L, Name),
+ NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
+ IsTypeName(IsTypeNameArg) {
}
public:
@@ -1776,28 +1728,37 @@ public:
/// preceding the namespace name.
SourceRange getNestedNameRange() { return NestedNameRange; }
- /// \brief Returns the source location of the target declaration name.
- SourceLocation getTargetNameLocation() { return TargetNameLocation; }
-
/// \brief Returns the source location of the "using" location itself.
SourceLocation getUsingLocation() { return UsingLocation; }
- /// \brief getTargetDecl - Returns target specified by using-decl.
- NamedDecl *getTargetDecl() { return TargetDecl; }
- const NamedDecl *getTargetDecl() const { return TargetDecl; }
-
/// \brief Get target nested name declaration.
NestedNameSpecifier* getTargetNestedNameDecl() {
- return TargetNestedNameDecl;
+ return TargetNestedName;
}
/// isTypeName - Return true if using decl has 'typename'.
bool isTypeName() const { return IsTypeName; }
+ typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator;
+ shadow_iterator shadow_begin() const { return Shadows.begin(); }
+ shadow_iterator shadow_end() const { return Shadows.end(); }
+
+ void addShadowDecl(UsingShadowDecl *S) {
+ assert(S->getUsingDecl() == this);
+ if (!Shadows.insert(S)) {
+ assert(false && "declaration already in set");
+ }
+ }
+ void removeShadowDecl(UsingShadowDecl *S) {
+ assert(S->getUsingDecl() == this);
+ if (!Shadows.erase(S)) {
+ assert(false && "declaration not in set");
+ }
+ }
+
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
- SourceLocation UL, NamedDecl* Target,
- NestedNameSpecifier* TargetNNS, bool IsTypeNameArg);
+ SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
+ NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
static bool classof(const Decl *D) {
return D->getKind() == Decl::Using;
@@ -1805,31 +1766,88 @@ public:
static bool classof(const UsingDecl *D) { return true; }
};
-/// UnresolvedUsingDecl - Represents a using declaration whose name can not
-/// yet be resolved.
-class UnresolvedUsingDecl : public NamedDecl {
+/// UnresolvedUsingValueDecl - Represents a dependent using
+/// declaration which was not marked with 'typename'. Unlike
+/// non-dependent using declarations, these *only* bring through
+/// non-types; otherwise they would break two-phase lookup.
+///
+/// template <class T> class A : public Base<T> {
+/// using Base<T>::foo;
+/// };
+class UnresolvedUsingValueDecl : public ValueDecl {
/// \brief The source range that covers the nested-name-specifier
/// preceding the declaration name.
SourceRange TargetNestedNameRange;
- /// \brief The source location of the target declaration name.
- SourceLocation TargetNameLocation;
+ /// \brief The source location of the 'using' keyword
+ SourceLocation UsingLocation;
NestedNameSpecifier *TargetNestedNameSpecifier;
- DeclarationName TargetName;
+ UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
+ SourceLocation UsingLoc, SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc,
+ DeclarationName TargetName)
+ : ValueDecl(Decl::UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TargetNestedNameSpecifier(TargetNNS)
+ { }
- // \brief Has 'typename' keyword.
- bool IsTypeName;
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
- UnresolvedUsingDecl(DeclContext *DC, SourceLocation UsingLoc,
- SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc, DeclarationName TargetName,
- bool IsTypeNameArg)
- : NamedDecl(Decl::UnresolvedUsing, DC, UsingLoc, TargetName),
- TargetNestedNameRange(TargetNNR), TargetNameLocation(TargetNameLoc),
- TargetNestedNameSpecifier(TargetNNS), TargetName(TargetName),
- IsTypeName(IsTypeNameArg) { }
+ /// \brief Get target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameSpecifier() {
+ return TargetNestedNameSpecifier;
+ }
+
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
+
+ static UnresolvedUsingValueDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, DeclarationName TargetName);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::UnresolvedUsingValue;
+ }
+ static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
+};
+
+/// UnresolvedUsingTypenameDecl - Represents a dependent using
+/// declaration which was marked with 'typename'.
+///
+/// template <class T> class A : public Base<T> {
+/// using typename Base<T>::foo;
+/// };
+///
+/// The type associated with a unresolved using typename decl is
+/// currently always a typename type.
+class UnresolvedUsingTypenameDecl : public TypeDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange TargetNestedNameRange;
+
+ /// \brief The source location of the 'using' keyword
+ SourceLocation UsingLocation;
+
+ /// \brief The source location of the 'typename' keyword
+ SourceLocation TypenameLocation;
+
+ NestedNameSpecifier *TargetNestedNameSpecifier;
+
+ UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, IdentifierInfo *TargetName)
+ : TypeDecl(Decl::UnresolvedUsingTypename, DC, TargetNameLoc, TargetName),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
+ { }
public:
/// \brief Returns the source range that covers the nested-name-specifier
@@ -1841,26 +1859,22 @@ public:
return TargetNestedNameSpecifier;
}
- /// \brief Returns the source location of the target declaration name.
- SourceLocation getTargetNameLocation() const { return TargetNameLocation; }
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
- /// \brief Returns the source location of the target declaration name.
- DeclarationName getTargetName() const { return TargetName; }
-
- bool isTypeName() const { return IsTypeName; }
+ /// \brief Returns the source location of the 'typename' keyword.
+ SourceLocation getTypenameLoc() const { return TypenameLocation; }
- static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation UsingLoc,
- SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc,
- DeclarationName TargetName,
- bool IsTypeNameArg);
+ static UnresolvedUsingTypenameDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, DeclarationName TargetName);
static bool classof(const Decl *D) {
- return D->getKind() == Decl::UnresolvedUsing;
+ return D->getKind() == Decl::UnresolvedUsingTypename;
}
- static bool classof(const UnresolvedUsingDecl *D) { return true; }
+ static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
};
/// StaticAssertDecl - Represents a C++0x static_assert declaration.
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index d9e40d478907..c2b48cee36f4 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -14,8 +14,9 @@
#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
-#include "clang/AST/DeclBase.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclCXX.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def
index 3ef3cc3f0975..ec1b3b055cab 100644
--- a/include/clang/AST/DeclNodes.def
+++ b/include/clang/AST/DeclNodes.def
@@ -81,6 +81,7 @@ ABSTRACT_DECL(Named, Decl)
DECL(NamespaceAlias, NamedDecl)
ABSTRACT_DECL(Type, NamedDecl)
DECL(Typedef, TypeDecl)
+ DECL(UnresolvedUsingTypename, TypeDecl)
ABSTRACT_DECL(Tag, TypeDecl)
DECL(Enum, TagDecl)
DECL(Record, TagDecl)
@@ -91,6 +92,7 @@ ABSTRACT_DECL(Named, Decl)
DECL(TemplateTypeParm, TypeDecl)
ABSTRACT_DECL(Value, NamedDecl)
DECL(EnumConstant, ValueDecl)
+ DECL(UnresolvedUsingValue, ValueDecl)
ABSTRACT_DECL(Declarator, ValueDecl)
DECL(Function, DeclaratorDecl)
DECL(CXXMethod, FunctionDecl)
@@ -109,7 +111,7 @@ ABSTRACT_DECL(Named, Decl)
DECL(ClassTemplate, TemplateDecl)
DECL(TemplateTemplateParm, TemplateDecl)
DECL(Using, NamedDecl)
- DECL(UnresolvedUsing, NamedDecl)
+ DECL(UsingShadow, NamedDecl)
DECL(ObjCMethod, NamedDecl)
DECL(ObjCContainer, NamedDecl)
DECL(ObjCCategory, ObjCContainerDecl)
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index bcd28eab039f..13193ffab55e 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -718,10 +718,22 @@ public:
/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
///
class ObjCClassDecl : public Decl {
- ObjCList<ObjCInterfaceDecl> ForwardDecls;
+public:
+ class ObjCClassRef {
+ ObjCInterfaceDecl *ID;
+ SourceLocation L;
+ public:
+ ObjCClassRef(ObjCInterfaceDecl *d, SourceLocation l) : ID(d), L(l) {}
+ SourceLocation getLocation() const { return L; }
+ ObjCInterfaceDecl *getInterface() const { return ID; }
+ };
+private:
+ ObjCClassRef *ForwardDecls;
+ unsigned NumDecls;
ObjCClassDecl(DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const *Elts, unsigned nElts, ASTContext &C);
+ ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
+ unsigned nElts, ASTContext &C);
virtual ~ObjCClassDecl() {}
public:
@@ -730,17 +742,19 @@ public:
static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts = 0,
+ const SourceLocation *Locs = 0,
unsigned nElts = 0);
+
+ virtual SourceRange getSourceRange() const;
- typedef ObjCList<ObjCInterfaceDecl>::iterator iterator;
- iterator begin() const { return ForwardDecls.begin(); }
- iterator end() const { return ForwardDecls.end(); }
- unsigned size() const { return ForwardDecls.size(); }
+ typedef const ObjCClassRef* iterator;
+ iterator begin() const { return ForwardDecls; }
+ iterator end() const { return ForwardDecls + NumDecls; }
+ unsigned size() const { return NumDecls; }
/// setClassList - Set the list of forward classes.
- void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, unsigned Num) {
- ForwardDecls.set(List, Num, C);
- }
+ void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
+ const SourceLocation *Locs, unsigned Num);
static bool classof(const Decl *D) { return D->getKind() == ObjCClass; }
static bool classof(const ObjCClassDecl *D) { return true; }
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index f1a27933a1b3..14f666005cd6 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -699,13 +699,13 @@ class TemplateTemplateParmDecl
: public TemplateDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any.
- Expr *DefaultArgument;
+ TemplateArgumentLoc DefaultArgument;
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
unsigned D, unsigned P,
IdentifierInfo *Id, TemplateParameterList *Params)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
- TemplateParmPosition(D, P), DefaultArgument(0)
+ TemplateParmPosition(D, P), DefaultArgument()
{ }
public:
@@ -720,16 +720,17 @@ public:
/// \brief Determine whether this template parameter has a default
/// argument.
- bool hasDefaultArgument() const { return DefaultArgument; }
+ bool hasDefaultArgument() const {
+ return !DefaultArgument.getArgument().isNull();
+ }
/// \brief Retrieve the default argument, if any.
- Expr *getDefaultArgument() const { return DefaultArgument; }
-
- /// \brief Retrieve the location of the default argument, if any.
- SourceLocation getDefaultArgumentLoc() const;
+ const TemplateArgumentLoc &getDefaultArgument() const {
+ return DefaultArgument;
+ }
/// \brief Set the default argument for this template parameter.
- void setDefaultArgument(Expr *DefArg) {
+ void setDefaultArgument(const TemplateArgumentLoc &DefArg) {
DefaultArgument = DefArg;
}
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index ed4ac6b5d4e7..a30f6e860dde 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -176,7 +176,6 @@ public:
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
-
/// getName - Retrieve the human-readable string for this name.
std::string getAsString() const;
@@ -249,6 +248,8 @@ public:
static DeclarationName getTombstoneMarker() {
return DeclarationName(uintptr_t(-2));
}
+
+ void dump() const;
};
/// Ordering on two declaration names. If both names are identifiers,
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 2a87f5883588..dfc5b13f28d3 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -87,7 +87,7 @@ public:
// type. Additionally, inspect Expr::isLvalue to determine whether
// an expression that is adjusted in this manner should be
// considered an lvalue.
- assert((TR.isNull() || !TR->isReferenceType()) &&
+ assert((t.isNull() || !t->isReferenceType()) &&
"Expressions can't have reference type");
TR = t;
@@ -250,6 +250,12 @@ public:
/// folded, but discard the result.
bool isEvaluatable(ASTContext &Ctx) const;
+ /// HasSideEffects - This routine returns true for all those expressions
+ /// which must be evaluated each time and must not be optimization away
+ /// or evaluated at compile time. Example is a function call, volatile
+ /// variable read.
+ bool HasSideEffects(ASTContext &Ctx) const;
+
/// EvaluateAsInt - Call Evaluate and return the folded integer. This
/// must be called on an expression that constant folds to an integer.
llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const;
@@ -1513,6 +1519,9 @@ public:
/// CK_NoOp - Used for const_cast.
CK_NoOp,
+ /// CK_BaseToDerived - Base to derived class casts.
+ CK_BaseToDerived,
+
/// CK_DerivedToBase - Derived to base class casts.
CK_DerivedToBase,
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 5931a3fcf984..9e6fd4fd065b 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -95,6 +95,8 @@ public:
/// operation would return "x".
Expr *getImplicitObjectArgument();
+ virtual SourceRange getSourceRange() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
}
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 5f318ba0b33b..9b1c640a40b2 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -15,6 +15,8 @@
#define LLVM_CLANG_AST_LAYOUTINFO_H
#include "llvm/System/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/DeclCXX.h"
namespace clang {
class ASTContext;
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 1e6871ff3b9c..867932332d09 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_REDECLARABLE_H
#include "llvm/ADT/PointerIntPair.h"
+#include <iterator>
namespace clang {
@@ -23,6 +24,8 @@ template<typename decl_type>
class Redeclarable {
protected:
+ // FIXME: PointerIntPair is a value class that should not be inherited from.
+ // This should change to using containment.
struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> {
DeclLink(decl_type *D, bool isLatest)
: llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { }
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index bb14c62d7770..6db095872b0e 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/Support/ErrorHandling.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TemplateName.h"
namespace llvm {
class FoldingSetNodeID;
@@ -48,21 +49,27 @@ class TemplateArgument {
public:
/// \brief The type of template argument we're storing.
enum ArgKind {
+ /// \brief Represents an empty template argument, e.g., one that has not
+ /// been deduced.
Null = 0,
/// The template argument is a type. Its value is stored in the
/// TypeOrValue field.
- Type = 1,
- /// The template argument is a declaration
- Declaration = 2,
- /// The template argument is an integral value stored in an llvm::APSInt.
- Integral = 3,
+ Type,
+ /// The template argument is a declaration that was provided for a pointer
+ /// or reference non-type template parameter.
+ Declaration,
+ /// The template argument is an integral value stored in an llvm::APSInt
+ /// that was provided for an integral non-type template parameter.
+ Integral,
+ /// The template argument is a template name that was provided for a
+ /// template template parameter.
+ Template,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
- Expression = 4,
-
+ Expression,
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
- Pack = 5
+ Pack
} Kind;
/// \brief Construct an empty, invalid template argument.
@@ -82,12 +89,21 @@ public:
}
/// \brief Construct an integral constant template argument.
- TemplateArgument(const llvm::APSInt &Value, QualType Type)
- : Kind(Integral) {
+ TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
new (Integer.Value) llvm::APSInt(Value);
Integer.Type = Type.getAsOpaquePtr();
}
+ /// \brief Construct a template argument that is a template.
+ ///
+ /// This form of template argument is generally used for template template
+ /// parameters. However, the template name could be a dependent template
+ /// name that ends up being instantiated to a function template whose address
+ /// is taken.
+ TemplateArgument(TemplateName Name) : Kind(Template) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+ }
+
/// \brief Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
@@ -172,6 +188,15 @@ public:
return reinterpret_cast<Decl *>(TypeOrValue);
}
+ /// \brief Retrieve the template argument as a template name.
+ TemplateName getAsTemplate() const {
+ if (Kind != Template)
+ return TemplateName();
+
+ return TemplateName::getFromVoidPointer(
+ reinterpret_cast<void *> (TypeOrValue));
+ }
+
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
if (Kind != Integral)
@@ -242,13 +267,18 @@ private:
union {
Expr *Expression;
DeclaratorInfo *Declarator;
+ struct {
+ unsigned QualifierRange[2];
+ unsigned TemplateNameLoc;
+ } Template;
};
#ifndef NDEBUG
enum Kind {
K_None,
K_DeclaratorInfo,
- K_Expression
+ K_Expression,
+ K_Template
} Kind;
#endif
@@ -273,6 +303,17 @@ public:
, Kind(K_Expression)
#endif
{}
+
+ TemplateArgumentLocInfo(SourceRange QualifierRange,
+ SourceLocation TemplateNameLoc)
+#ifndef NDEBUG
+ : Kind(K_Template)
+#endif
+ {
+ Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
+ Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
+ Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+ }
DeclaratorInfo *getAsDeclaratorInfo() const {
assert(Kind == K_DeclaratorInfo);
@@ -284,6 +325,18 @@ public:
return Expression;
}
+ SourceRange getTemplateQualifierRange() const {
+ assert(Kind == K_Template);
+ return SourceRange(
+ SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
+ SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ assert(Kind == K_Template);
+ return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
+ }
+
#ifndef NDEBUG
void validateForArgument(const TemplateArgument &Arg) {
switch (Arg.getKind()) {
@@ -294,6 +347,9 @@ public:
case TemplateArgument::Declaration:
assert(Kind == K_Expression);
break;
+ case TemplateArgument::Template:
+ assert(Kind == K_Template);
+ break;
case TemplateArgument::Integral:
case TemplateArgument::Pack:
assert(Kind == K_None);
@@ -329,8 +385,18 @@ public:
assert(Argument.getKind() == TemplateArgument::Expression);
}
- /// \brief - Fetches the start location of the argument.
+ TemplateArgumentLoc(const TemplateArgument &Argument,
+ SourceRange QualifierRange,
+ SourceLocation TemplateNameLoc)
+ : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
+ assert(Argument.getKind() == TemplateArgument::Template);
+ }
+
+ /// \brief - Fetches the primary location of the argument.
SourceLocation getLocation() const {
+ if (Argument.getKind() == TemplateArgument::Template)
+ return getTemplateNameLoc();
+
return getSourceRange().getBegin();
}
@@ -359,6 +425,16 @@ public:
assert(Argument.getKind() == TemplateArgument::Declaration);
return LocInfo.getAsExpr();
}
+
+ SourceRange getTemplateQualifierRange() const {
+ assert(Argument.getKind() == TemplateArgument::Template);
+ return LocInfo.getTemplateQualifierRange();
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ assert(Argument.getKind() == TemplateArgument::Template);
+ return LocInfo.getTemplateNameLoc();
+ }
};
}
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index daa814739182..c28bafe9a30f 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -396,10 +396,6 @@ class QualType {
llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>,
Qualifiers::FastWidth> Value;
- bool hasExtQuals() const {
- return Value.getPointer().is<const ExtQuals*>();
- }
-
const ExtQuals *getExtQualsUnsafe() const {
return Value.getPointer().get<const ExtQuals*>();
}
@@ -408,6 +404,8 @@ class QualType {
return Value.getPointer().get<const Type*>();
}
+ QualType getUnqualifiedTypeSlow() const;
+
friend class QualifierCollector;
public:
QualType() {}
@@ -417,14 +415,14 @@ public:
QualType(const ExtQuals *Ptr, unsigned Quals)
: Value(Ptr, Quals) {}
- unsigned getFastQualifiers() const { return Value.getInt(); }
- void setFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
+ unsigned getLocalFastQualifiers() const { return Value.getInt(); }
+ void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
/// Retrieves a pointer to the underlying (unqualified) type.
/// This should really return a const Type, but it's not worth
/// changing all the users right now.
Type *getTypePtr() const {
- if (hasNonFastQualifiers())
+ if (hasLocalNonFastQualifiers())
return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
return const_cast<Type*>(getTypePtrUnsafe());
}
@@ -452,41 +450,81 @@ public:
return Value.getPointer().isNull();
}
- bool isConstQualified() const {
- return (getFastQualifiers() & Qualifiers::Const);
- }
- bool isRestrictQualified() const {
- return (getFastQualifiers() & Qualifiers::Restrict);
- }
- bool isVolatileQualified() const {
- return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
- }
-
- // Determines whether this type has any direct qualifiers.
- bool hasQualifiers() const {
- return getFastQualifiers() || hasNonFastQualifiers();
- }
-
- bool hasNonFastQualifiers() const {
- return hasExtQuals();
+ /// \brief Determine whether this particular QualType instance has the
+ /// "const" qualifier set, without looking through typedefs that may have
+ /// added "const" at a different level.
+ bool isLocalConstQualified() const {
+ return (getLocalFastQualifiers() & Qualifiers::Const);
+ }
+
+ /// \brief Determine whether this type is const-qualified.
+ bool isConstQualified() const;
+
+ /// \brief Determine whether this particular QualType instance has the
+ /// "restrict" qualifier set, without looking through typedefs that may have
+ /// added "restrict" at a different level.
+ bool isLocalRestrictQualified() const {
+ return (getLocalFastQualifiers() & Qualifiers::Restrict);
+ }
+
+ /// \brief Determine whether this type is restrict-qualified.
+ bool isRestrictQualified() const;
+
+ /// \brief Determine whether this particular QualType instance has the
+ /// "volatile" qualifier set, without looking through typedefs that may have
+ /// added "volatile" at a different level.
+ bool isLocalVolatileQualified() const {
+ return (hasLocalNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
+ }
+
+ /// \brief Determine whether this type is volatile-qualified.
+ bool isVolatileQualified() const;
+
+ /// \brief Determine whether this particular QualType instance has any
+ /// qualifiers, without looking through any typedefs that might add
+ /// qualifiers at a different level.
+ bool hasLocalQualifiers() const {
+ return getLocalFastQualifiers() || hasLocalNonFastQualifiers();
+ }
+
+ /// \brief Determine whether this type has any qualifiers.
+ bool hasQualifiers() const;
+
+ /// \brief Determine whether this particular QualType instance has any
+ /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType
+ /// instance.
+ bool hasLocalNonFastQualifiers() const {
+ return Value.getPointer().is<const ExtQuals*>();
}
- // Retrieves the set of qualifiers belonging to this type.
- Qualifiers getQualifiers() const {
+ /// \brief Retrieve the set of qualifiers local to this particular QualType
+ /// instance, not including any qualifiers acquired through typedefs or
+ /// other sugar.
+ Qualifiers getLocalQualifiers() const {
Qualifiers Quals;
- if (hasNonFastQualifiers())
+ if (hasLocalNonFastQualifiers())
Quals = getExtQualsUnsafe()->getQualifiers();
- Quals.addFastQualifiers(getFastQualifiers());
+ Quals.addFastQualifiers(getLocalFastQualifiers());
return Quals;
}
- // Retrieves the CVR qualifiers of this type.
- unsigned getCVRQualifiers() const {
- unsigned CVR = getFastQualifiers();
- if (isVolatileQualified()) CVR |= Qualifiers::Volatile;
+ /// \brief Retrieve the set of qualifiers applied to this type.
+ Qualifiers getQualifiers() const;
+
+ /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
+ /// local to this particular QualType instance, not including any qualifiers
+ /// acquired through typedefs or other sugar.
+ unsigned getLocalCVRQualifiers() const {
+ unsigned CVR = getLocalFastQualifiers();
+ if (isLocalVolatileQualified())
+ CVR |= Qualifiers::Volatile;
return CVR;
}
+ /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
+ /// applied to this type.
+ unsigned getCVRQualifiers() const;
+
bool isConstant(ASTContext& Ctx) const {
return QualType::isConstant(*this, Ctx);
}
@@ -508,6 +546,9 @@ public:
Value.setInt(Value.getInt() | TQs);
}
+ // FIXME: The remove* functions are semantically broken, because they might
+ // not remove a qualifier stored on a typedef. Most of the with* functions
+ // have the same problem.
void removeConst();
void removeVolatile();
void removeRestrict();
@@ -540,8 +581,21 @@ public:
return T;
}
- QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); }
+ /// \brief Return this type with all of the instance-specific qualifiers
+ /// removed, but without removing any qualifiers that may have been applied
+ /// through typedefs.
+ QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); }
+ /// \brief Return the unqualified form of the given type, which might be
+ /// desugared to eliminate qualifiers introduced via typedefs.
+ QualType getUnqualifiedType() const {
+ QualType T = getLocalUnqualifiedType();
+ if (!T.hasQualifiers())
+ return T;
+
+ return getUnqualifiedTypeSlow();
+ }
+
bool isMoreQualifiedThan(QualType Other) const;
bool isAtLeastAsQualifiedAs(QualType Other) const;
QualType getNonReferenceType() const;
@@ -892,8 +946,6 @@ public:
QualType getCanonicalTypeInternal() const { return CanonicalType; }
void dump() const;
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const = 0;
static bool classof(const Type *) { return true; }
};
@@ -963,8 +1015,21 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
+ bool isInteger() const {
+ return TypeKind >= Bool && TypeKind <= Int128;
+ }
+
+ bool isSignedInteger() const {
+ return TypeKind >= Char_S && TypeKind <= Int128;
+ }
+
+ bool isUnsignedInteger() const {
+ return TypeKind >= Bool && TypeKind <= UInt128;
+ }
+
+ bool isFloatingPoint() const {
+ return TypeKind >= Float && TypeKind <= LongDouble;
+ }
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
static bool classof(const BuiltinType *) { return true; }
@@ -988,9 +1053,6 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; }
static bool classof(const FixedWidthIntType *) { return true; }
};
@@ -1008,9 +1070,6 @@ class ComplexType : public Type, public llvm::FoldingSetNode {
public:
QualType getElementType() const { return ElementType; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1036,9 +1095,6 @@ class PointerType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
public:
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
QualType getPointeeType() const { return PointeeType; }
bool isSugared() const { return false; }
@@ -1071,9 +1127,6 @@ public:
// Get the pointee type. Pointee is required to always be a function type.
QualType getPointeeType() const { return PointeeType; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1157,9 +1210,6 @@ class LValueReferenceType : public ReferenceType {
{}
friend class ASTContext; // ASTContext creates these
public:
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1177,9 +1227,6 @@ class RValueReferenceType : public ReferenceType {
}
friend class ASTContext; // ASTContext creates these
public:
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1209,9 +1256,6 @@ public:
const Type *getClass() const { return Class; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1302,9 +1346,6 @@ protected:
friend class ASTContext; // ASTContext creates these.
public:
const llvm::APInt &getSize() const { return Size; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1336,9 +1377,6 @@ class IncompleteArrayType : public ArrayType {
: ArrayType(IncompleteArray, et, can, sm, tq) {}
friend class ASTContext; // ASTContext creates these.
public:
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1402,9 +1440,6 @@ public:
SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1458,9 +1493,6 @@ public:
SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1510,9 +1542,6 @@ public:
QualType getElementType() const { return ElementType; }
SourceLocation getAttributeLoc() const { return loc; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1555,9 +1584,6 @@ public:
QualType getElementType() const { return ElementType; }
unsigned getNumElements() const { return NumElements; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1633,9 +1659,6 @@ public:
return unsigned(idx-1) < NumElements;
return false;
}
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1699,9 +1722,6 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
public:
// No additional state past what FunctionType provides.
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1812,9 +1832,6 @@ public:
return exception_begin() + NumExceptions;
}
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -1856,9 +1873,6 @@ public:
bool isSugared() const { return true; }
QualType desugar() const;
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
static bool classof(const TypedefType *) { return true; }
};
@@ -1879,9 +1893,6 @@ public:
/// \brief Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; }
static bool classof(const TypeOfExprType *) { return true; }
};
@@ -1924,9 +1935,6 @@ public:
/// \brief Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
static bool classof(const TypeOfType *) { return true; }
};
@@ -1953,9 +1961,6 @@ public:
/// \brief Returns whether this type directly provides sugar.
bool isSugared() const { return !isDependentType(); }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
static bool classof(const Type *T) { return T->getTypeClass() == Decltype; }
static bool classof(const DecltypeType *) { return true; }
};
@@ -2000,9 +2005,6 @@ public:
bool isBeingDefined() const { return decl.getInt(); }
void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
static bool classof(const Type *T) {
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
}
@@ -2117,9 +2119,6 @@ public:
}
}
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getUnderlyingType(), getTagKind());
}
@@ -2155,9 +2154,6 @@ public:
bool isParameterPack() const { return ParameterPack; }
IdentifierInfo *getName() const { return Name; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2211,9 +2207,6 @@ public:
return getCanonicalTypeInternal();
}
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return true; }
QualType desugar() const { return getReplacementType(); }
@@ -2309,9 +2302,6 @@ public:
/// \precondition @c isArgType(Arg)
const TemplateArgument &getArg(unsigned Idx) const;
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return !isDependentType(); }
QualType desugar() const { return getCanonicalTypeInternal(); }
@@ -2363,9 +2353,6 @@ public:
/// \brief Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, NNS, NamedType);
}
@@ -2440,9 +2427,6 @@ public:
return Name.dyn_cast<const TemplateSpecializationType *>();
}
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2493,9 +2477,6 @@ public:
qual_iterator qual_end() const { return Protocols.end(); }
bool qual_empty() const { return Protocols.size() == 0; }
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2581,8 +2562,6 @@ public:
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
ObjCProtocolDecl **protocols, unsigned NumProtocols);
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
static bool classof(const Type *T) {
return T->getTypeClass() == ObjCObjectPointer;
}
@@ -2604,8 +2583,8 @@ public:
/// Collect any qualifiers on the given type and return an
/// unqualified type.
const Type *strip(QualType QT) {
- addFastQualifiers(QT.getFastQualifiers());
- if (QT.hasNonFastQualifiers()) {
+ addFastQualifiers(QT.getLocalFastQualifiers());
+ if (QT.hasLocalNonFastQualifiers()) {
const ExtQuals *EQ = QT.getExtQualsUnsafe();
Context = &EQ->getContext();
addQualifiers(EQ->getQualifiers());
@@ -2627,18 +2606,51 @@ public:
inline bool QualType::isCanonical() const {
const Type *T = getTypePtr();
- if (hasQualifiers())
+ if (hasLocalQualifiers())
return T->isCanonicalUnqualified() && !isa<ArrayType>(T);
return T->isCanonicalUnqualified();
}
inline bool QualType::isCanonicalAsParam() const {
- if (hasQualifiers()) return false;
+ if (hasLocalQualifiers()) return false;
const Type *T = getTypePtr();
return T->isCanonicalUnqualified() &&
!isa<FunctionType>(T) && !isa<ArrayType>(T);
}
+inline bool QualType::isConstQualified() const {
+ return isLocalConstQualified() ||
+ getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified();
+}
+
+inline bool QualType::isRestrictQualified() const {
+ return isLocalRestrictQualified() ||
+ getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified();
+}
+
+
+inline bool QualType::isVolatileQualified() const {
+ return isLocalVolatileQualified() ||
+ getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified();
+}
+
+inline bool QualType::hasQualifiers() const {
+ return hasLocalQualifiers() ||
+ getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers();
+}
+
+inline Qualifiers QualType::getQualifiers() const {
+ Qualifiers Quals = getLocalQualifiers();
+ Quals.addQualifiers(
+ getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers());
+ return Quals;
+}
+
+inline unsigned QualType::getCVRQualifiers() const {
+ return getLocalCVRQualifiers() |
+ getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers();
+}
+
inline void QualType::removeConst() {
removeFastQualifiers(Qualifiers::Const);
}
@@ -2673,14 +2685,14 @@ inline void QualType::removeCVRQualifiers(unsigned Mask) {
/// getAddressSpace - Return the address space of this type.
inline unsigned QualType::getAddressSpace() const {
- if (hasNonFastQualifiers()) {
+ if (hasLocalNonFastQualifiers()) {
const ExtQuals *EQ = getExtQualsUnsafe();
if (EQ->hasAddressSpace())
return EQ->getAddressSpace();
}
QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (CT.hasNonFastQualifiers()) {
+ if (CT.hasLocalNonFastQualifiers()) {
const ExtQuals *EQ = CT.getExtQualsUnsafe();
if (EQ->hasAddressSpace())
return EQ->getAddressSpace();
@@ -2695,14 +2707,14 @@ inline unsigned QualType::getAddressSpace() const {
/// getObjCGCAttr - Return the gc attribute of this type.
inline Qualifiers::GC QualType::getObjCGCAttr() const {
- if (hasNonFastQualifiers()) {
+ if (hasLocalNonFastQualifiers()) {
const ExtQuals *EQ = getExtQualsUnsafe();
if (EQ->hasObjCGCAttr())
return EQ->getObjCGCAttr();
}
QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (CT.hasNonFastQualifiers()) {
+ if (CT.hasLocalNonFastQualifiers()) {
const ExtQuals *EQ = CT.getExtQualsUnsafe();
if (EQ->hasObjCGCAttr())
return EQ->getObjCGCAttr();
@@ -2780,28 +2792,26 @@ inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const {
return 0;
}
-// NOTE: All of these methods use "getUnqualifiedType" to strip off address
-// space qualifiers if present.
inline bool Type::isFunctionType() const {
- return isa<FunctionType>(CanonicalType.getUnqualifiedType());
+ return isa<FunctionType>(CanonicalType);
}
inline bool Type::isPointerType() const {
- return isa<PointerType>(CanonicalType.getUnqualifiedType());
+ return isa<PointerType>(CanonicalType);
}
inline bool Type::isAnyPointerType() const {
return isPointerType() || isObjCObjectPointerType();
}
inline bool Type::isBlockPointerType() const {
- return isa<BlockPointerType>(CanonicalType.getUnqualifiedType());
+ return isa<BlockPointerType>(CanonicalType);
}
inline bool Type::isReferenceType() const {
- return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
+ return isa<ReferenceType>(CanonicalType);
}
inline bool Type::isLValueReferenceType() const {
- return isa<LValueReferenceType>(CanonicalType.getUnqualifiedType());
+ return isa<LValueReferenceType>(CanonicalType);
}
inline bool Type::isRValueReferenceType() const {
- return isa<RValueReferenceType>(CanonicalType.getUnqualifiedType());
+ return isa<RValueReferenceType>(CanonicalType);
}
inline bool Type::isFunctionPointerType() const {
if (const PointerType* T = getAs<PointerType>())
@@ -2810,7 +2820,7 @@ inline bool Type::isFunctionPointerType() const {
return false;
}
inline bool Type::isMemberPointerType() const {
- return isa<MemberPointerType>(CanonicalType.getUnqualifiedType());
+ return isa<MemberPointerType>(CanonicalType);
}
inline bool Type::isMemberFunctionPointerType() const {
if (const MemberPointerType* T = getAs<MemberPointerType>())
@@ -2819,37 +2829,37 @@ inline bool Type::isMemberFunctionPointerType() const {
return false;
}
inline bool Type::isArrayType() const {
- return isa<ArrayType>(CanonicalType.getUnqualifiedType());
+ return isa<ArrayType>(CanonicalType);
}
inline bool Type::isConstantArrayType() const {
- return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType());
+ return isa<ConstantArrayType>(CanonicalType);
}
inline bool Type::isIncompleteArrayType() const {
- return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType());
+ return isa<IncompleteArrayType>(CanonicalType);
}
inline bool Type::isVariableArrayType() const {
- return isa<VariableArrayType>(CanonicalType.getUnqualifiedType());
+ return isa<VariableArrayType>(CanonicalType);
}
inline bool Type::isDependentSizedArrayType() const {
- return isa<DependentSizedArrayType>(CanonicalType.getUnqualifiedType());
+ return isa<DependentSizedArrayType>(CanonicalType);
}
inline bool Type::isRecordType() const {
- return isa<RecordType>(CanonicalType.getUnqualifiedType());
+ return isa<RecordType>(CanonicalType);
}
inline bool Type::isAnyComplexType() const {
- return isa<ComplexType>(CanonicalType.getUnqualifiedType());
+ return isa<ComplexType>(CanonicalType);
}
inline bool Type::isVectorType() const {
- return isa<VectorType>(CanonicalType.getUnqualifiedType());
+ return isa<VectorType>(CanonicalType);
}
inline bool Type::isExtVectorType() const {
- return isa<ExtVectorType>(CanonicalType.getUnqualifiedType());
+ return isa<ExtVectorType>(CanonicalType);
}
inline bool Type::isObjCObjectPointerType() const {
- return isa<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType());
+ return isa<ObjCObjectPointerType>(CanonicalType);
}
inline bool Type::isObjCInterfaceType() const {
- return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
+ return isa<ObjCInterfaceType>(CanonicalType);
}
inline bool Type::isObjCQualifiedIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
@@ -2875,7 +2885,7 @@ inline bool Type::isObjCBuiltinType() const {
return isObjCIdType() || isObjCClassType();
}
inline bool Type::isTemplateTypeParmType() const {
- return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
+ return isa<TemplateTypeParmType>(CanonicalType);
}
inline bool Type::isSpecificBuiltinType(unsigned K) const {
@@ -2911,8 +2921,21 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
+// Helper class template that is used by Type::getAs to ensure that one does
+// not try to look through a qualified type to get to an array type.
+template<typename T,
+ bool isArrayType = (llvm::is_same<T, ArrayType>::value ||
+ llvm::is_base_of<ArrayType, T>::value)>
+struct ArrayType_cannot_be_used_with_getAs { };
+
+template<typename T>
+struct ArrayType_cannot_be_used_with_getAs<T, true>;
+
/// Member-template getAs<specific type>'.
template <typename T> const T *Type::getAs() const {
+ ArrayType_cannot_be_used_with_getAs<T> at;
+ (void)at;
+
// If this is directly a T type, return it.
if (const T *Ty = dyn_cast<T>(this))
return Ty;
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index da7857822e9c..f08ca6bf469b 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -58,7 +58,7 @@ public:
: Ty(ty), Data(opaqueData) { }
TypeLocClass getTypeLocClass() const {
- if (getType().hasQualifiers()) return Qualified;
+ if (getType().hasLocalQualifiers()) return Qualified;
return (TypeLocClass) getType()->getTypeClass();
}
@@ -155,7 +155,7 @@ public:
}
static bool classof(const TypeLoc *TL) {
- return !TL->getType().hasQualifiers();
+ return !TL->getType().hasLocalQualifiers();
}
static bool classof(const UnqualTypeLoc *TL) { return true; }
};
@@ -196,11 +196,11 @@ public:
/// \brief Returns the size of the type source info data block.
unsigned getFullDataSize() const {
return getLocalDataSize() +
- getFullDataSizeForType(getType().getUnqualifiedType());
+ getFullDataSizeForType(getType().getLocalUnqualifiedType());
}
static bool classof(const TypeLoc *TL) {
- return TL->getType().hasQualifiers();
+ return TL->getType().hasLocalQualifiers();
}
static bool classof(const QualifiedTypeLoc *TL) { return true; }
};
@@ -919,6 +919,10 @@ public:
Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
break;
+ case TemplateArgument::Template:
+ Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation());
+ break;
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h
index 4e1fbaaf4c5e..00e2b7f83219 100644
--- a/include/clang/AST/TypeLocBuilder.h
+++ b/include/clang/AST/TypeLocBuilder.h
@@ -17,6 +17,7 @@
#include "clang/AST/TypeLoc.h"
#include "llvm/ADT/SmallVector.h"
+#include "clang/AST/ASTContext.h"
namespace clang {
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 17f772da0c6d..867494396020 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -88,11 +88,11 @@ public:
/// dumpLiveness - Print to stderr the liveness information encoded
/// by a specified bitvector.
- void dumpLiveness(const ValTy& V, SourceManager& M) const;
+ void dumpLiveness(const ValTy& V, const SourceManager& M) const;
/// dumpBlockLiveness - Print to stderr the liveness information
/// associated with each basic block.
- void dumpBlockLiveness(SourceManager& M) const;
+ void dumpBlockLiveness(const SourceManager& M) const;
/// getNumDecls - Return the number of variables (declarations) that
/// whose liveness status is being tracked by the dataflow
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
index f505bca9519c..cbf7010bfdb5 100644
--- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h
+++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -16,6 +16,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Analysis/FlowSensitive/DataflowValues.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "functional" // STL
diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h
index 1da15fbae6c4..8c70e4fc7b6c 100644
--- a/include/clang/Analysis/LocalCheckers.h
+++ b/include/clang/Analysis/LocalCheckers.h
@@ -50,10 +50,12 @@ void CheckObjCInstMethSignature(const ObjCImplementationDecl *ID,
void CheckObjCUnusedIvar(const ObjCImplementationDecl *D, BugReporter& BR);
void RegisterAppleChecks(GRExprEngine& Eng, const Decl &D);
+void RegisterExperimentalChecks(GRExprEngine &Eng);
+void RegisterExperimentalInternalChecks(GRExprEngine &Eng);
void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR);
-
+void CheckSizeofPointer(const Decl *D, BugReporter &BR);
} // end namespace clang
#endif
diff --git a/include/clang/Analysis/ManagerRegistry.h b/include/clang/Analysis/ManagerRegistry.h
new file mode 100644
index 000000000000..972993855c28
--- /dev/null
+++ b/include/clang/Analysis/ManagerRegistry.h
@@ -0,0 +1,53 @@
+//===-- ManagerRegistry.h - Pluggable analyzer module registry --*- 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 ManagerRegistry and Register* classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H
+#define LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H
+
+#include "clang/Analysis/PathSensitive/GRState.h"
+
+namespace clang {
+
+/// ManagerRegistry - This class records manager creators registered at
+/// runtime. The information is communicated to AnalysisManager through static
+/// members. Better design is expected.
+
+class ManagerRegistry {
+public:
+ static StoreManagerCreator StoreMgrCreator;
+ static ConstraintManagerCreator ConstraintMgrCreator;
+};
+
+/// RegisterConstraintManager - This class is used to setup the constraint
+/// manager of the static analyzer. The constructor takes a creator function
+/// pointer for creating the constraint manager.
+///
+/// It is used like this:
+///
+/// class MyConstraintManager {};
+/// ConstraintManager* CreateMyConstraintManager(GRStateManager& statemgr) {
+/// return new MyConstraintManager(statemgr);
+/// }
+/// RegisterConstraintManager X(CreateMyConstraintManager);
+
+class RegisterConstraintManager {
+public:
+ RegisterConstraintManager(ConstraintManagerCreator CMC) {
+ assert(ManagerRegistry::ConstraintMgrCreator == 0
+ && "ConstraintMgrCreator already set!");
+ ManagerRegistry::ConstraintMgrCreator = CMC;
+ }
+};
+
+}
+#endif
diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h
index 66e850a91444..9b58f745f0a5 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisContext.h
+++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
+#include "clang/AST/Stmt.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h
index 488334623b34..18eae9ac9f14 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisManager.h
+++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h
@@ -37,7 +37,6 @@ class AnalysisManager : public BugReporterData {
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
- bool DisplayedFunction;
bool VisualizeEGDot;
bool VisualizeEGUbi;
bool PurgeDead;
@@ -62,7 +61,7 @@ public:
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
- AScope(ScopeDecl), DisplayedFunction(!displayProgress),
+ AScope(ScopeDecl),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim) {}
@@ -120,8 +119,6 @@ public:
bool shouldEagerlyAssume() const { return EagerlyAssume; }
- void DisplayFunction(Decl *D);
-
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
}
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h
index 914118cb430d..f4297350ec70 100644
--- a/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -81,10 +81,10 @@ public:
getOriginalNode(const ExplodedNode* N) = 0;
};
- BugReport(BugType& bt, const char* desc, const ExplodedNode *n)
+ BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *n)
: BT(bt), Description(desc), EndNode(n) {}
- BugReport(BugType& bt, const char* shortDesc, const char* desc,
+ BugReport(BugType& bt, llvm::StringRef shortDesc, llvm::StringRef desc,
const ExplodedNode *n)
: BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {}
@@ -193,11 +193,11 @@ public:
class RangedBugReport : public BugReport {
std::vector<SourceRange> Ranges;
public:
- RangedBugReport(BugType& D, const char* description, ExplodedNode *n)
+ RangedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n)
: BugReport(D, description, n) {}
- RangedBugReport(BugType& D, const char *shortDescription,
- const char *description, ExplodedNode *n)
+ RangedBugReport(BugType& D, llvm::StringRef shortDescription,
+ llvm::StringRef description, ExplodedNode *n)
: BugReport(D, shortDescription, description, n) {}
~RangedBugReport();
@@ -229,11 +229,11 @@ private:
Creators creators;
public:
- EnhancedBugReport(BugType& D, const char* description, ExplodedNode *n)
+ EnhancedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n)
: RangedBugReport(D, description, n) {}
- EnhancedBugReport(BugType& D, const char *shortDescription,
- const char *description, ExplodedNode *n)
+ EnhancedBugReport(BugType& D, llvm::StringRef shortDescription,
+ llvm::StringRef description, ExplodedNode *n)
: RangedBugReport(D, shortDescription, description, n) {}
~EnhancedBugReport() {}
diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h
index 242b8e9afebe..8303dee49afa 100644
--- a/include/clang/Analysis/PathSensitive/BugType.h
+++ b/include/clang/Analysis/PathSensitive/BugType.h
@@ -23,6 +23,7 @@ class BugReportEquivClass;
class BugReporter;
class BuiltinBugReport;
class BugReporterContext;
+class ExplodedNode;
class GRExprEngine;
class BugType {
@@ -59,21 +60,27 @@ public:
};
class BuiltinBug : public BugType {
- GRExprEngine &Eng;
+ GRExprEngine *Eng;
protected:
const std::string desc;
public:
+ BuiltinBug(const char *name, const char *description)
+ : BugType(name, "Logic error"), Eng(0), desc(description) {}
+
+ BuiltinBug(const char *name)
+ : BugType(name, "Logic error"), Eng(0), desc(name) {}
+
BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
- : BugType(n, "Logic error"), Eng(*eng), desc(d) {}
+ : BugType(n, "Logic error"), Eng(eng), desc(d) {}
BuiltinBug(GRExprEngine *eng, const char* n)
- : BugType(n, "Logic error"), Eng(*eng), desc(n) {}
+ : BugType(n, "Logic error"), Eng(eng), desc(n) {}
const std::string &getDescription() const { return desc; }
virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
- void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
+ void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, *Eng); }
virtual void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode* N,
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h
index 4fc0a617ecf0..b7ed20fab250 100644
--- a/include/clang/Analysis/PathSensitive/Checker.h
+++ b/include/clang/Analysis/PathSensitive/Checker.h
@@ -39,22 +39,19 @@ class CheckerContext {
SaveAndRestore<const void*> OldTag;
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
SaveOr OldHasGen;
+ const GRState *state;
public:
- CheckerContext(ExplodedNodeSet &dst,
- GRStmtNodeBuilder &builder,
- GRExprEngine &eng,
- ExplodedNode *pred,
- const void *tag, bool preVisit)
+ CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder,
+ GRExprEngine &eng, ExplodedNode *pred,
+ const void *tag, ProgramPoint::Kind K,
+ const GRState *st = 0)
: Dst(dst), B(builder), Eng(eng), Pred(pred),
- OldSink(B.BuildSinks), OldTag(B.Tag),
- OldPointKind(B.PointKind), OldHasGen(B.HasGeneratedNode) {
- //assert(Dst.empty()); // This is a fake assertion.
- // See GRExprEngine::CheckerVisit(), CurrSet is repeatedly used.
- B.Tag = tag;
- if (preVisit)
- B.PointKind = ProgramPoint::PreStmtKind;
- }
+ OldSink(B.BuildSinks),
+ OldTag(B.Tag, tag),
+ OldPointKind(B.PointKind, K),
+ OldHasGen(B.HasGeneratedNode),
+ state(st) {}
~CheckerContext() {
if (!B.BuildSinks && !B.HasGeneratedNode)
@@ -64,10 +61,15 @@ public:
ConstraintManager &getConstraintManager() {
return Eng.getConstraintManager();
}
+
+ StoreManager &getStoreManager() {
+ return Eng.getStoreManager();
+ }
+
ExplodedNodeSet &getNodeSet() { return Dst; }
GRStmtNodeBuilder &getNodeBuilder() { return B; }
ExplodedNode *&getPredecessor() { return Pred; }
- const GRState *getState() { return B.GetState(Pred); }
+ const GRState *getState() { return state ? state : B.GetState(Pred); }
ASTContext &getASTContext() {
return Eng.getContext();
@@ -76,6 +78,10 @@ public:
BugReporter &getBugReporter() {
return Eng.getBugReporter();
}
+
+ SourceManager &getSourceManager() {
+ return getBugReporter().getSourceManager();
+ }
ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
return GenerateNode(S, getState(), markAsSink);
@@ -104,50 +110,69 @@ class Checker {
private:
friend class GRExprEngine;
+ // FIXME: Remove the 'tag' option.
void GR_Visit(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder,
GRExprEngine &Eng,
- const Stmt *stmt,
+ const Stmt *S,
ExplodedNode *Pred, void *tag, bool isPrevisit) {
- CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
- assert(isPrevisit && "Only previsit supported for now.");
- _PreVisit(C, stmt);
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind);
+ if (isPrevisit)
+ _PreVisit(C, S);
+ else
+ _PostVisit(C, S);
}
+ // FIXME: Remove the 'tag' option.
void GR_VisitBind(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
const Stmt *AssignE,
const Stmt *StoreE, ExplodedNode *Pred, void *tag,
SVal location, SVal val,
bool isPrevisit) {
- CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind);
assert(isPrevisit && "Only previsit supported for now.");
PreVisitBind(C, AssignE, StoreE, location, val);
}
-
-public:
- virtual ~Checker() {}
- virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {}
- // This is a previsit which takes a node returns a node.
- virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V,
- GRExprEngine &Eng) {
- return Pred;
+ // FIXME: Remove the 'tag' option.
+ void GR_VisitLocation(ExplodedNodeSet &Dst,
+ GRStmtNodeBuilder &Builder,
+ GRExprEngine &Eng,
+ const Stmt *S,
+ ExplodedNode *Pred, const GRState *state,
+ SVal location,
+ void *tag, bool isLoad) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isLoad ? ProgramPoint::PreLoadKind :
+ ProgramPoint::PreStoreKind, state);
+ VisitLocation(C, S, location);
}
-
- virtual void PreVisitBind(CheckerContext &C,
- const Stmt *AssignE, const Stmt *StoreE,
- SVal location, SVal val) {}
-
- virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
- const GRState *state, Stmt *S,
- GRExprEngine &Eng) {
- return Pred;
+
+ void GR_EvalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
+ GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
+ SymbolReaper &SymReaper, void *tag) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ ProgramPoint::PostPurgeDeadSymbolsKind, Pred->getState());
+ EvalDeadSymbols(C, S, SymReaper);
}
+public:
+ virtual ~Checker() {}
+ virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
+ virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
+ virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
+ const Stmt *StoreE, SVal location, SVal val) {}
+ virtual void EvalDeadSymbols(CheckerContext &C, const Stmt *S,
+ SymbolReaper &SymReaper) {}
+ virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
+ GRExprEngine &Eng) {}
};
-
} // end clang namespace
#endif
diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def
index ff6528dae8f5..090a5d397549 100644
--- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def
+++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def
@@ -11,8 +11,19 @@
//
//===---------------------------------------------------------------------===//
+#ifdef PREVISIT
+PREVISIT(ArraySubscriptExpr)
+PREVISIT(BinaryOperator)
PREVISIT(CallExpr)
+PREVISIT(CastExpr)
+PREVISIT(DeclStmt)
PREVISIT(ObjCMessageExpr)
-PREVISIT(BinaryOperator)
-
+PREVISIT(ReturnStmt)
#undef PREVISIT
+#endif
+
+#ifdef POSTVISIT
+POSTVISIT(CallExpr)
+#undef POSTVISIT
+#endif
+
diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Analysis/PathSensitive/CheckerVisitor.h
index e74f49c9a761..7cef17eb6591 100644
--- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h
+++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.h
@@ -27,8 +27,12 @@ namespace clang {
template<typename ImplClass>
class CheckerVisitor : public Checker {
public:
- virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) {
- PreVisit(C, stmt);
+ virtual void _PreVisit(CheckerContext &C, const Stmt *S) {
+ PreVisit(C, S);
+ }
+
+ virtual void _PostVisit(CheckerContext &C, const Stmt *S) {
+ PostVisit(C, S);
}
void PreVisit(CheckerContext &C, const Stmt *S) {
@@ -36,10 +40,19 @@ public:
default:
assert(false && "Unsupport statement.");
return;
+
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::ExplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ static_cast<ImplClass*>(this)->PreVisitCastExpr(C,
+ static_cast<const CastExpr*>(S));
+ break;
+
case Stmt::CompoundAssignOperatorClass:
static_cast<ImplClass*>(this)->PreVisitBinaryOperator(C,
static_cast<const BinaryOperator*>(S));
break;
+
#define PREVISIT(NAME) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\
@@ -47,13 +60,30 @@ break;
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
}
}
+
+ void PostVisit(CheckerContext &C, const Stmt *S) {
+ switch (S->getStmtClass()) {
+ default:
+ assert(false && "Unsupport statement.");
+ return;
+#define POSTVISIT(NAME) \
+case Stmt::NAME ## Class:\
+static_cast<ImplClass*>(this)->\
+PostVisit ## NAME(C,static_cast<const NAME*>(S));\
+break;
+#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
+ }
+ }
#define PREVISIT(NAME) \
void PreVisit ## NAME(CheckerContext &C, const NAME* S) {}
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
+
+#define POSTVISIT(NAME) \
+void PostVisit ## NAME(CheckerContext &C, const NAME* S) {}
+#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
};
} // end clang namespace
#endif
-
diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
index 688cf641491d..a84183e7f27f 100644
--- a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
+++ b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
@@ -16,38 +16,16 @@
#ifndef LLVM_CLANG_DEREFCHECKER
#define LLVM_CLANG_DEREFCHECKER
-#include "clang/Analysis/PathSensitive/Checker.h"
-#include "clang/Analysis/PathSensitive/BugType.h"
+#include <utility>
namespace clang {
+class GRExprEngine;
class ExplodedNode;
-class NullDerefChecker : public Checker {
- BuiltinBug *BT;
- llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
-
-public:
- NullDerefChecker() : BT(0) {}
- ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V,GRExprEngine &Eng);
-
- static void *getTag();
- typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator;
- iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); }
- iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); }
-};
-
-class UndefDerefChecker : public Checker {
- BuiltinBug *BT;
-public:
- UndefDerefChecker() : BT(0) {}
-
- ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V, GRExprEngine &Eng);
-
- static void *getTag();
-};
+std::pair<ExplodedNode * const *, ExplodedNode * const *>
+GetImplicitNullDereferences(GRExprEngine &Eng);
} // end clang namespace
+
#endif
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index 25e47038d72c..1b6d0bdf9c10 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -111,14 +111,6 @@ public:
// was larger than sizeof(void *) (an undefined value).
ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit;
- /// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
- /// the address of a stack variable.
- ErrorNodes RetsStackAddr;
-
- /// RetsUndef - Nodes in the ExplodedGraph that result from returning
- /// an undefined value.
- ErrorNodes RetsUndef;
-
/// UndefBranches - Nodes in the ExplodedGraph that result from
/// taking a branch based on an undefined value.
ErrorNodes UndefBranches;
@@ -131,22 +123,10 @@ public:
// calling a function with the attribute "noreturn".
ErrorNodes NoReturnCalls;
- /// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
- /// constructing a zero-sized VLA where the size may be zero.
- ErrorNodes ImplicitBadSizedVLA;
-
- /// ExplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
- /// constructing a zero-sized VLA where the size must be zero.
- ErrorNodes ExplicitBadSizedVLA;
-
/// UndefResults - Nodes in the ExplodedGraph where the operands are defined
/// by the result is not. Excludes divide-by-zero errors.
ErrorNodes UndefResults;
- /// BadCalls - Nodes in the ExplodedGraph resulting from calls to function
- /// pointers that are NULL (or other constants) or Undefined.
- ErrorNodes BadCalls;
-
/// UndefReceiver - Nodes in the ExplodedGraph resulting from message
/// ObjC message expressions where the receiver is undefined (uninitialized).
ErrorNodes UndefReceivers;
@@ -156,14 +136,6 @@ public:
/// value.
UndefArgsTy MsgExprUndefArgs;
- /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
- /// out-of-bound memory accesses where the index MAY be out-of-bound.
- ErrorNodes ImplicitOOBMemAccesses;
-
- /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
- /// out-of-bound memory accesses where the index MUST be out-of-bound.
- ErrorNodes ExplicitOOBMemAccesses;
-
public:
GRExprEngine(AnalysisManager &mgr);
@@ -223,58 +195,10 @@ public:
return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
}
- bool isRetStackAddr(const ExplodedNode* N) const {
- return N->isSink() && RetsStackAddr.count(const_cast<ExplodedNode*>(N)) != 0;
- }
-
- bool isUndefControlFlow(const ExplodedNode* N) const {
- return N->isSink() && UndefBranches.count(const_cast<ExplodedNode*>(N)) != 0;
- }
-
- bool isUndefStore(const ExplodedNode* N) const {
- return N->isSink() && UndefStores.count(const_cast<ExplodedNode*>(N)) != 0;
- }
-
- bool isImplicitNullDeref(const ExplodedNode* N) const {
- return false;
- }
-
- bool isExplicitNullDeref(const ExplodedNode* N) const {
- return false;
- }
-
- bool isUndefDeref(const ExplodedNode* N) const {
- return false;
- }
-
bool isNoReturnCall(const ExplodedNode* N) const {
return N->isSink() && NoReturnCalls.count(const_cast<ExplodedNode*>(N)) != 0;
}
- bool isUndefResult(const ExplodedNode* N) const {
- return N->isSink() && UndefResults.count(const_cast<ExplodedNode*>(N)) != 0;
- }
-
- bool isBadCall(const ExplodedNode* N) const {
- return false;
- }
-
- bool isUndefArg(const ExplodedNode* N) const {
- return false;
- }
-
- bool isUndefReceiver(const ExplodedNode* N) const {
- return N->isSink() && UndefReceivers.count(const_cast<ExplodedNode*>(N)) != 0;
- }
-
- typedef ErrorNodes::iterator ret_stackaddr_iterator;
- ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
- ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }
-
- typedef ErrorNodes::iterator ret_undef_iterator;
- ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); }
- ret_undef_iterator ret_undef_end() { return RetsUndef.end(); }
-
typedef ErrorNodes::iterator undef_branch_iterator;
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
@@ -305,10 +229,6 @@ public:
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
- typedef ErrorNodes::iterator bad_calls_iterator;
- bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); }
- bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
-
typedef UndefArgsTy::iterator undef_arg_iterator;
undef_arg_iterator msg_expr_undef_arg_begin() {
return MsgExprUndefArgs.begin();
@@ -327,20 +247,6 @@ public:
return UndefReceivers.end();
}
- typedef ErrorNodes::iterator oob_memacc_iterator;
- oob_memacc_iterator implicit_oob_memacc_begin() {
- return ImplicitOOBMemAccesses.begin();
- }
- oob_memacc_iterator implicit_oob_memacc_end() {
- return ImplicitOOBMemAccesses.end();
- }
- oob_memacc_iterator explicit_oob_memacc_begin() {
- return ExplicitOOBMemAccesses.begin();
- }
- oob_memacc_iterator explicit_oob_memacc_end() {
- return ExplicitOOBMemAccesses.end();
- }
-
void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
void AddCheck(GRSimpleAPICheck* A);
@@ -368,10 +274,7 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
- void ProcessEndPath(GREndPathNodeBuilder& builder) {
- getTF().EvalEndPath(*this, builder);
- StateMgr.EndPath(builder.getState());
- }
+ void ProcessEndPath(GREndPathNodeBuilder& builder);
GRStateManager& getStateManager() { return StateMgr; }
const GRStateManager& getStateManager() const { return StateMgr; }
@@ -516,9 +419,6 @@ protected:
void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
- const GRState* CheckDivideZero(Expr* Ex, const GRState* St, ExplodedNode* Pred,
- SVal Denom);
-
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions.
@@ -553,15 +453,11 @@ public:
}
protected:
- void EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, ExplodedNode* Pred);
-
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
}
- void EvalReturn(ExplodedNodeSet& Dst, ReturnStmt* s, ExplodedNode* Pred);
-
const GRState* MarkBranch(const GRState* St, Stmt* Terminator,
bool branchTaken);
@@ -573,16 +469,22 @@ protected:
bool atDeclInit = false);
public:
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
- const GRState* St, SVal location, const void *tag = 0);
+ const GRState* St, SVal location, const void *tag = 0,
+ QualType LoadTy = QualType());
- ExplodedNode* EvalLocation(Stmt* Ex, ExplodedNode* Pred,
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
+ void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
- const void *tag = 0);
+ const void *tag, bool isLoad);
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE,
- ExplodedNode* Pred,
- const GRState* St, SVal TargetLV, SVal Val,
+ ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0);
};
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index 8678ca9b5b9b..ef0c36c44d9f 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -195,6 +195,9 @@ public:
//
const GRState *Assume(DefinedOrUnknownSVal cond, bool assumption) const;
+
+ std::pair<const GRState*, const GRState*>
+ Assume(DefinedOrUnknownSVal cond) const;
const GRState *AssumeInBound(DefinedOrUnknownSVal idx,
DefinedOrUnknownSVal upperBound,
@@ -330,12 +333,6 @@ public:
void printStdErr() const;
void printDOT(llvm::raw_ostream& Out) const;
-
- // Tags used for the Generic Data Map.
- struct NullDerefTag {
- static int TagInt;
- typedef const SVal* data_type;
- };
};
class GRStateSet {
@@ -403,10 +400,6 @@ private:
/// Alloc - A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator& Alloc;
- /// CurrentStmt - The block-level statement currently being visited. This
- /// is set by GRExprEngine.
- Stmt* CurrentStmt;
-
/// TF - Object that represents a bundle of transfer functions
/// for manipulating and creating SVals.
GRTransferFuncs* TF;
@@ -583,6 +576,15 @@ inline const GRState *GRState::Assume(DefinedOrUnknownSVal Cond,
return getStateManager().ConstraintMgr->Assume(this, cast<DefinedSVal>(Cond),
Assumption);
}
+
+inline std::pair<const GRState*, const GRState*>
+GRState::Assume(DefinedOrUnknownSVal Cond) const {
+ if (Cond.isUnknown())
+ return std::make_pair(this, this);
+
+ return getStateManager().ConstraintMgr->AssumeDual(this,
+ cast<DefinedSVal>(Cond));
+}
inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
DefinedOrUnknownSVal UpperBound,
diff --git a/include/clang/Analysis/PathSensitive/GRWorkList.h b/include/clang/Analysis/PathSensitive/GRWorkList.h
index 17b83fdf9fdc..857fa316911f 100644
--- a/include/clang/Analysis/PathSensitive/GRWorkList.h
+++ b/include/clang/Analysis/PathSensitive/GRWorkList.h
@@ -16,16 +16,19 @@
#define LLVM_CLANG_ANALYSIS_GRWORKLIST
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
+#include <cstddef>
namespace clang {
-
+
+class CFGBlock;
+class ExplodedNode;
class ExplodedNodeImpl;
class GRWorkListUnit {
ExplodedNode* Node;
GRBlockCounter Counter;
CFGBlock* Block;
- unsigned BlockIdx;
+ unsigned BlockIdx; // This is the index of the next statement.
public:
GRWorkListUnit(ExplodedNode* N, GRBlockCounter C,
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index 0e487691a891..06d0d976df01 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -77,6 +77,8 @@ public:
const MemRegion *getBaseRegion() const;
+ const MemRegion *StripCasts() const;
+
bool hasStackStorage() const;
bool hasParametersStorage() const;
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h
index 4ba3c7396822..8b5cf40e29cb 100644
--- a/include/clang/Analysis/PathSensitive/SVals.h
+++ b/include/clang/Analysis/PathSensitive/SVals.h
@@ -96,6 +96,8 @@ public:
return getRawKind() > UnknownKind;
}
+ bool isConstant() const;
+
bool isZeroConstant() const;
/// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
@@ -434,7 +436,7 @@ public:
return static_cast<MemRegion*>(Data);
}
- const MemRegion* getBaseRegion() const;
+ const MemRegion* StripCasts() const;
template <typename REGION>
const REGION* getRegionAs() const {
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 6ca2e9e9aa68..55fa83d9ecc3 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -102,7 +102,8 @@ public:
virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0;
// FIXME: Make out-of-line.
- virtual SVal getSizeInElements(const GRState *state, const MemRegion *region){
+ virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
+ const MemRegion *region) {
return UnknownVal();
}
@@ -180,8 +181,7 @@ protected:
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
- SValuator::CastResult CastRetrievedVal(SVal val, const GRState *state,
- const TypedRegion *R, QualType castTy);
+ SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy);
};
// FIXME: Do we still need this?
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 7aaae9c86653..78827dfabe2f 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -33,13 +33,10 @@ public:
BlockEntranceKind,
BlockExitKind,
PreStmtKind,
- // Keep the following together and in this order.
PostStmtKind,
- PostLocationChecksSucceedKind,
- PostOutOfBoundsCheckFailedKind,
- PostNullCheckFailedKind,
- PostUndefLocationCheckFailedKind,
+ PreLoadKind,
PostLoadKind,
+ PreStoreKind,
PostStoreKind,
PostPurgeDeadSymbolsKind,
PostStmtCustomKind,
@@ -194,17 +191,6 @@ public:
}
};
-class PostLocationChecksSucceed : public PostStmt {
-public:
- PostLocationChecksSucceed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostLocationChecksSucceedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostLocationChecksSucceedKind;
- }
-};
-
class PostStmtCustom : public PostStmt {
public:
PostStmtCustom(const Stmt* S,
@@ -226,36 +212,36 @@ public:
}
};
-class PostOutOfBoundsCheckFailed : public PostStmt {
-public:
- PostOutOfBoundsCheckFailed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostOutOfBoundsCheckFailedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostOutOfBoundsCheckFailedKind;
+
+class LocationCheck : public StmtPoint {
+protected:
+ LocationCheck(const Stmt *S, const LocationContext *L,
+ ProgramPoint::Kind K, const void *tag)
+ : StmtPoint(S, NULL, K, L, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ unsigned k = location->getKind();
+ return k == PreLoadKind || k == PreStoreKind;
}
};
-
-class PostUndefLocationCheckFailed : public PostStmt {
+
+class PreLoad : public LocationCheck {
public:
- PostUndefLocationCheckFailed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostUndefLocationCheckFailedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostUndefLocationCheckFailedKind;
+ PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0)
+ : LocationCheck(S, L, PreLoadKind, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ return location->getKind() == PreLoadKind;
}
};
-class PostNullCheckFailed : public PostStmt {
+class PreStore : public LocationCheck {
public:
- PostNullCheckFailed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostNullCheckFailedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostNullCheckFailedKind;
+ PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0)
+ : LocationCheck(S, L, PreStoreKind, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ return location->getKind() == PreStoreKind;
}
};
diff --git a/include/clang/Analysis/Support/Optional.h b/include/clang/Analysis/Support/Optional.h
index 3940007bb574..40f38be020a9 100644
--- a/include/clang/Analysis/Support/Optional.h
+++ b/include/clang/Analysis/Support/Optional.h
@@ -39,6 +39,9 @@ public:
} //end clang namespace
namespace llvm {
+
+template<typename T> struct simplify_type;
+
template <typename T>
struct simplify_type<const ::clang::Optional<T> > {
typedef const T* SimpleType;
diff --git a/include/clang/Analysis/Support/SaveAndRestore.h b/include/clang/Analysis/Support/SaveAndRestore.h
index 4720c22d990e..f720639490d9 100644
--- a/include/clang/Analysis/Support/SaveAndRestore.h
+++ b/include/clang/Analysis/Support/SaveAndRestore.h
@@ -22,6 +22,9 @@ namespace clang {
template<typename T>
struct SaveAndRestore {
SaveAndRestore(T& x) : X(x), old_value(x) {}
+ SaveAndRestore(T& x, const T &new_value) : X(x), old_value(x) {
+ X = new_value;
+ }
~SaveAndRestore() { X = old_value; }
T get() { return old_value; }
private:
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 77a2079b766d..3a70e134b82b 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -32,6 +32,7 @@ namespace clang {
class IdentifierInfo;
class LangOptions;
class PartialDiagnostic;
+ class Preprocessor;
class SourceRange;
// Import the diagnostic enums themselves.
@@ -105,6 +106,10 @@ public:
/// modification is known.
CodeModificationHint() : RemoveRange(), InsertionLoc() { }
+ bool isNull() const {
+ return !RemoveRange.isValid() && !InsertionLoc.isValid();
+ }
+
/// \brief Create a code modification hint that inserts the given
/// code string at a specific location.
static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc,
@@ -382,6 +387,7 @@ public:
/// @c Pos represents the source location associated with the diagnostic,
/// which can be an invalid location if no position information is available.
inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
+ inline DiagnosticBuilder Report(unsigned DiagID);
/// \brief Clear out the current diagnostic.
void Clear() { CurDiagID = ~0U; }
@@ -586,6 +592,9 @@ public:
}
void AddCodeModificationHint(const CodeModificationHint &Hint) const {
+ if (Hint.isNull())
+ return;
+
assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
"Too many code modification hints!");
if (DiagObj)
@@ -664,6 +673,9 @@ inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){
CurDiagID = DiagID;
return DiagnosticBuilder(this);
}
+inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
+ return Report(FullSourceLoc(), DiagID);
+}
//===----------------------------------------------------------------------===//
// DiagnosticInfo
@@ -780,7 +792,8 @@ public:
/// \arg LO - The language options for the source file being processed.
/// \arg PP - The preprocessor object being used for the source; this optional
/// and may not be present, for example when processing AST source files.
- virtual void BeginSourceFile(const LangOptions &LangOpts) {}
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP = 0) {}
/// EndSourceFile - Callback to inform the diagnostic client that processing
/// of a source file has ended. The diagnostic client should assume that any
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index bb251ad73bd8..9a342b592ca5 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -52,4 +52,11 @@ def warn_integer_too_large_for_signed : Warning<
def note_invalid_subexpr_in_ice : Note<
"subexpression not valid in an integer constant expression">;
+// Targets
+
+def err_target_unknown_triple : Error<
+ "unknown target triple '%0', please use -triple or -arch">;
+def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
+def err_target_invalid_feature : Error<"invalid target feature '%0'">;
+
}
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index ae8b92394443..e9b351ffe995 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -9,19 +9,33 @@
let Component = "Frontend" in {
-def err_fe_unknown_triple : Error<
- "unknown target triple '%0', please use -triple or -arch">;
-def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">;
def err_fe_error_opening : Error<"error opening '%0': %1">;
def err_fe_error_reading : Error<"error reading '%0'">;
def err_fe_error_reading_stdin : Error<"error reading stdin">;
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
-def err_fe_invalid_code_complete_file
+def err_fe_invalid_code_complete_file
: Error<"cannot locate code-completion file %0">, DefaultFatal;
def err_fe_dependency_file_requires_MT : Error<
"-dependency-file requires at least one -MT option">;
+def err_fe_incompatible_options : Error<
+ "'%0' cannot be used with '%1'">, DefaultFatal;
+def err_fe_no_fixit_and_codegen : Error<
+ "FIX-ITs cannot be applied when generating code">;
+def err_fe_unable_to_find_fixit_file : Error<
+ "FIX-IT could not find file '%0'">;
+def err_fe_invalid_plugin_name : Error<
+ "unable to find plugin '%0'">;
+
+def err_verify_bogus_characters : Error<
+ "bogus characters before '{{' in expected string">;
+def err_verify_missing_start : Error<
+ "cannot find start ('{{') of expected string">;
+def err_verify_missing_end : Error<
+ "cannot find end ('}}') of expected string">;
+def err_verify_inconsistent_diags : Error<
+ "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: %2">;
def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
def note_fixit_in_macro : Note<
@@ -162,6 +176,9 @@ def warn_pch_access_control : Error<
def warn_pch_char_signed : Error<
"char was %select{unsigned|signed}0 in the PCH file but "
"is currently %select{unsigned|signed}1">;
+def warn_pch_short_wchar : Error<
+ "-fshort-wchar was %select{disabled|enabled}0 in the PCH file but "
+ "is currently %select{disabled|enabled}1">;
def err_not_a_pch_file : Error<
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 8cfdd4095027..93c655b50500 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -28,7 +28,7 @@ def : DiagGroup<"cast-align">;
def : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">;
-def : DiagGroup<"conversion">;
+def : DiagGroup<"ctor-dtor-privacy">;
def : DiagGroup<"declaration-after-statement">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
@@ -40,6 +40,7 @@ def FormatExtraArgs : DiagGroup<"format-extra-args">;
def FormatZeroLength : DiagGroup<"format-zero-length">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def : DiagGroup<"idiomatic-parentheses">;
def : DiagGroup<"import">;
def : DiagGroup<"init-self">;
def : DiagGroup<"inline">;
@@ -58,19 +59,21 @@ def MismatchedTags : DiagGroup<"mismatched-tags">;
def : DiagGroup<"missing-field-initializers">;
def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">;
+def : DiagGroup<"non-virtual-dtor">;
def : DiagGroup<"old-style-definition">;
def : DiagGroup<"overflow">;
def : DiagGroup<"overloaded-virtual">;
def : DiagGroup<"packed">;
-def Parentheses : DiagGroup<"parentheses">;
def PointerArith : DiagGroup<"pointer-arith">;
def : DiagGroup<"pointer-to-int-cast">;
def : DiagGroup<"redundant-decls">;
def ReturnType : DiagGroup<"return-type">;
+def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
def : DiagGroup<"sequence-point">;
def : DiagGroup<"shadow">;
def : DiagGroup<"shorten-64-to-32">;
-def : DiagGroup<"sign-compare">;
+def SignCompare : DiagGroup<"sign-compare">;
+def : DiagGroup<"synth">;
// Preprocessor warnings.
def : DiagGroup<"builtin-macro-redefined">;
@@ -114,6 +117,14 @@ def CharSubscript : DiagGroup<"char-subscripts">;
// Aggregation warning settings.
+// -Widiomatic-parentheses contains warnings about 'idiomatic'
+// missing parentheses; it is off by default.
+def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]>;
+
+// -Wconversion has its own warnings, but we split this one out for
+// legacy reasons.
+def Conversion : DiagGroup<"conversion",
+ [DiagGroup<"shorten-64-to-32">]>;
def Unused : DiagGroup<"unused",
[UnusedArgument, UnusedFunction, UnusedLabel,
@@ -127,8 +138,9 @@ def FormatY2K : DiagGroup<"format-y2k", [Format]>;
def Format2 : DiagGroup<"format=2",
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
-
def Extra : DiagGroup<"extra", [
+ SemiBeforeMethodBody,
+ SignCompare,
UnusedParameter
]>;
@@ -158,3 +170,7 @@ def : DiagGroup<"all", [Most, Parentheses]>;
def : DiagGroup<"", [Extra]>; // -W = -Wextra
def : DiagGroup<"endif-labels", [ExtraTokens]>; // endif-labels = endif-tokens
+// A warning group for warnings that we want to have on by default in clang,
+// but which aren't on by default in GCC.
+def NonGCC : DiagGroup<"non-gcc",
+ [SignCompare, Conversion]>;
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index bbc551373d96..7f3f4ea1fca0 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -90,6 +90,14 @@ def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">;
def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">;
//===----------------------------------------------------------------------===//
+// PTH Diagnostics
+//===----------------------------------------------------------------------===//
+def err_pth_cannot_read : Error<
+ "PTH file '%0' could not be read">;
+def err_invalid_pth_file : Error<
+ "invalid or corrupt PTH file '%0'">;
+
+//===----------------------------------------------------------------------===//
// Preprocessor Diagnostics
//===----------------------------------------------------------------------===//
def pp_hash_warning : Warning<"#warning%0">, InGroup<DiagGroup<"#warnings">>;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index e173cffdfd2b..28c46cd2d707 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -201,9 +201,9 @@ def warn_expected_implementation : Warning<
"@end must appear in an @implementation context">;
def error_property_ivar_decl : Error<
"property synthesize requires specification of an ivar">;
-def warn_semicolon_before_method_nody : Warning<
+def warn_semicolon_before_method_body : Warning<
"semicolon before method body is ignored">,
- InGroup<DiagGroup<"semicolon-before-method-body">>;
+ InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore;
def err_expected_field_designator : Error<
"expected a field designator, such as '.field = 4'">;
@@ -230,7 +230,7 @@ def ext_ellipsis_exception_spec : Extension<
def err_expected_catch : Error<"expected catch">;
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
def err_using_namespace_in_class : Error<
- "'using namespace' in class not allowed">;
+ "'using namespace' is not allowed in classes">;
def err_ident_in_pseudo_dtor_not_a_type : Error<
"identifier %0 in pseudo-destructor expression does not name a type">;
@@ -289,6 +289,10 @@ def err_explicit_spec_non_template : Error<
def err_variadic_templates : Error<
"variadic templates are only allowed in C++0x">;
+def err_default_template_template_parameter_not_template : Error<
+ "default template argument for a template template parameter must be a class "
+ "template">;
+
// C++ declarations
def err_friend_decl_defines_class : Error<
"cannot define a type in a friend declaration">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 2309908df7b4..78a3ae5d47b7 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -103,6 +103,8 @@ def err_using_requires_qualname : Error<
"using declaration requires a qualified name">;
def err_using_typename_non_type : Error<
"'typename' keyword used on a non-type">;
+def err_using_dependent_value_is_type : Error<
+ "dependent using declaration resolved to type without 'typename'">;
def err_using_decl_nested_name_specifier_is_not_a_base_class : Error<
"using declaration refers into '%0', which is not a base class of %1">;
def err_using_decl_can_not_refer_to_class_member : Error<
@@ -115,6 +117,8 @@ def err_using_decl_destructor : Error<
"using declaration can not refer to a destructor">;
def err_using_decl_template_id : Error<
"using declaration can not refer to a template specialization">;
+def note_using_decl_target : Note<
+ "target of using declaration">;
def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">;
@@ -251,6 +255,7 @@ def warn_accessor_property_type_mismatch : Warning<
def note_declared_at : Note<"declared at">;
def err_setter_type_void : Error<"type of setter must be void">;
def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
+def warn_missing_atend : Warning<"'@end' is missing in implementation context">;
def err_objc_var_decl_inclass :
Error<"cannot declare variable inside @interface or @protocol">;
def error_missing_method_context : Error<
@@ -269,6 +274,9 @@ def warn_property_attr_mismatch : Warning<
def warn_objc_property_copy_missing_on_block : Warning<
"'copy' attribute must be specified for the block property "
"when -fobjc-gc-only is specified">;
+def warn_atomic_property_rule : Warning<
+ "writable atomic property %0 cannot pair a synthesized setter/getter "
+ "with a user defined setter/getter">;
def err_use_continuation_class : Error<
"property declaration in continuation class of %0 is to change a 'readonly' "
"property to 'readwrite'">;
@@ -397,7 +405,9 @@ def note_ambig_member_ref_scope : Note<
"lookup from the current scope refers here">;
def err_qualified_member_nonclass : Error<
"qualified member access refers to a member in %0">;
-
+def err_incomplete_member_access : Error<
+ "member access into incomplete type %0">;
+
// C++ class members
def err_storageclass_invalid_for_member : Error<
"storage class specified for a member declaration">;
@@ -430,9 +440,15 @@ def err_implicit_object_parameter_init : Error<
"cannot initialize object parameter of type %0 with an expression "
"of type %1">;
-def err_missing_default_constructor : Error<
- "default constructor for %1 is missing in initialization of "
- "%select{base class|member}0">;
+def note_field_decl : Note<"member is declared here">;
+def note_previous_class_decl : Note<
+ "%0 declared here">;
+def note_ctor_synthesized_at : Note<
+ "implicit default constructor for %0 first required here">;
+def err_missing_default_ctor : Error<
+ "%select{|implicit default }0constructor for %1 must explicitly initialize "
+ "the %select{base class|member}2 %3 which does not have a default "
+ "constructor">;
def err_illegal_union_member : Error<
"union member %0 has a non-trivial %select{constructor|"
"copy constructor|copy assignment operator|destructor}1">;
@@ -632,6 +648,25 @@ def err_cconv_knr : Error<
def err_cconv_varargs : Error<
"variadic function cannot use '%0' calling convention">;
+def warn_impcast_vector_scalar : Warning<
+ "implicit cast turns vector to scalar: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_complex_scalar : Warning<
+ "implicit cast discards imaginary component: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_float_precision : Warning<
+ "implicit cast loses floating-point precision: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_float_integer : Warning<
+ "implicit cast turns floating-point number into integer: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_precision : Warning<
+ "implicit cast loses integer precision: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_64_32 : Warning<
+ "implicit cast loses integer precision: %0 to %1">,
+ InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
+
def warn_attribute_ignored_for_field_of_type : Warning<
"%0 attribute ignored for field of type %1">;
def warn_transparent_union_attribute_field_size_align : Warning<
@@ -744,27 +779,18 @@ def err_param_default_argument_member_template_redecl : Error<
"default arguments cannot be added to an out-of-line definition of a member "
"of a %select{class template|class template partial specialization|nested "
"class in a template}0">;
-def note_field_decl : Note<"member is declared here">;
-def err_defining_default_ctor : Error<
- "cannot define the implicit default constructor for %0, because %select{base class|member's type}1 "
- "%2 does not have any default constructor">;
-def note_previous_class_decl : Note<
- "%0 declared here">;
def err_uninitialized_member_for_assign : Error<
"cannot define the implicit default assignment operator for %0, because "
"non-static %select{reference|const}1 member %2 can't use default "
"assignment operator">;
def note_first_required_here : Note<
"synthesized method is first required here">;
-def err_unintialized_member : Error<
- "cannot define the implicit default constructor for %0, because "
- "%select{reference|const}1 member %2 cannot be default-initialized">;
def err_null_intialized_reference_member : Error<
"cannot initialize the member to null in default constructor because "
"reference member %0 cannot be null-initialized">;
def err_unintialized_member_in_ctor : Error<
- "constructor for %0 must explicitly initialize the "
- "%select{reference|const}1 member %2 ">;
+ "%select{|implicit default }0constructor for %1 must explicitly initialize "
+ "the %select{reference|const}2 member %3">;
def err_use_of_default_argument_to_function_declared_later : Error<
"use of default argument to function %0 that is declared later in class %1">;
@@ -993,6 +1019,9 @@ def err_template_spec_friend : Error<
def err_template_spec_default_arg : Error<
"default argument not permitted on an explicit "
"%select{instantiation|specialization}0 of function %1">;
+def err_not_class_template_specialization : Error<
+ "cannot specialize a %select{dependent template|template template "
+ "parameter}0">;
// C++ class template specializations and out-of-line definitions
def err_template_spec_needs_header : Error<
@@ -1083,6 +1112,12 @@ def note_function_template_deduction_instantiation_here : Note<
def note_partial_spec_deduct_instantiation_here : Note<
"during template argument deduction for class template partial "
"specialization %0, here">;
+def note_prior_template_arg_substitution : Note<
+ "while substituting prior template arguments into %select{non-type|template}0"
+ " template parameter%1 %2">;
+def note_template_default_arg_checking : Note<
+ "while checking a default template argument used here">;
+
def err_field_instantiates_to_function : Error<
"data member instantiated with function type %0">;
def err_nested_name_spec_non_tag : Error<
@@ -1447,8 +1482,9 @@ def err_typecheck_member_reference_type : Error<
"cannot refer to type member %0 with '%select{.|->}1'">;
def err_typecheck_member_reference_unknown : Error<
"cannot refer to member %0 with '%select{.|->}1'">;
-def note_member_reference_needs_call : Note<
- "perhaps you meant to call this function with '()'?">;
+def err_member_reference_needs_call : Error<
+ "base of member reference has function type %0; perhaps you meant to call "
+ "this function with '()'?">;
def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
InGroup<CharSubscript>, DefaultIgnore;
@@ -1488,6 +1524,9 @@ def err_tentative_def_incomplete_type_arr : Error<
"tentative definition has array of type %0 that is never completed">;
def warn_tentative_incomplete_array : Warning<
"tentative array definition assumed to have one element">;
+def err_typecheck_incomplete_array_needs_initializer : Error<
+ "definition of variable with array type needs an explicit size "
+ "or an initializer">;
def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
def err_typecheck_sclass_fscope : Error<
@@ -1539,10 +1578,10 @@ def err_stmtexpr_file_scope : Error<
"statement expression not allowed at file scope">;
def warn_mixed_sign_comparison : Warning<
"comparison of integers of different signs: %0 and %1">,
- InGroup<DiagGroup<"sign-compare">>;
+ InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
def warn_mixed_sign_conditional : Warning<
"operands of ? are integers of different signs: %0 and %1">,
- InGroup<DiagGroup<"sign-compare">>;
+ InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
def err_invalid_this_use : Error<
"invalid use of 'this' outside of a nonstatic member function">;
@@ -1707,6 +1746,10 @@ def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
"expression of type %0 to a pointer">;
def warn_delete_incomplete : Warning<
"deleting pointer to incomplete type %0 may cause undefined behaviour">;
+def err_no_suitable_delete_member_function_found : Error<
+ "no suitable member %0 in %1">;
+def note_delete_member_function_declared_here : Note<
+ "%0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
def warn_increment_bool : Warning<
"incrementing expression of type bool is deprecated">;
@@ -1786,9 +1829,13 @@ def err_incomplete_object_call : Error<
def warn_condition_is_assignment : Warning<"using the result of an "
"assignment as a condition without parentheses">,
InGroup<Parentheses>;
+// Completely identical except off by default.
+def warn_condition_is_idiomatic_assignment : Warning<"using the result "
+ "of an assignment as a condition without parentheses">,
+ InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore;
-def warn_value_always_zero : Warning<"%0 is always zero in this context">;
-def warn_value_always_false : Warning<"%0 is always false in this context">;
+def warn_value_always_zero : Warning<
+ "%0 is always %select{zero|false|NULL}1 in this context">;
// assignment related diagnostics (also for argument passing, returning, etc).
// FIXME: %2 is an english string here.
@@ -1816,6 +1863,8 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn<
"incompatible pointer types %2 %1, expected %0">;
def ext_typecheck_convert_discards_qualifiers : ExtWarn<
"%2 %1 discards qualifiers, expected %0">;
+def ext_nested_pointer_qualifier_mismatch : ExtWarn<
+ "%2, %0 and %1 have different qualifiers in nested pointer types">;
def warn_incompatible_vectors : Warning<
"incompatible vector types %2 %1, expected %0">,
InGroup<VectorConversions>, DefaultIgnore;
@@ -2086,6 +2135,10 @@ def err_operator_overload_needs_class_or_enum : Error<
def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">;
def err_operator_overload_static : Error<
"overloaded %0 cannot be a static member function">;
+def err_operator_new_param_type : Error<
+ "%0 takes type size_t (%1) as first parameter">;
+def err_operator_new_result_type : Error<
+ "%0 must return type %1">;
def err_operator_overload_default_arg : Error<
"parameter of overloaded %0 cannot have a default argument">;
def err_operator_overload_must_be : Error<
@@ -2328,7 +2381,7 @@ def error_private_ivar_access : Error<"instance variable %0 is private">,
NoSFINAE;
def error_protected_ivar_access : Error<"instance variable %0 is protected">,
NoSFINAE;
-def warn_maynot_respond : Warning<"%0 may not respond to %1">;
+def warn_maynot_respond : Warning<"%0 may not respond to %1">;
def warn_attribute_method_def : Warning<
"method attribute can only be specified on method declarations">;
def ext_typecheck_base_super : Warning<
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index d4d3fe50eba0..99c100d55e7e 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -55,6 +55,7 @@ public:
unsigned POSIXThreads : 1; // Compiling with POSIX thread support
// (-pthread)
unsigned Blocks : 1; // block extension to C
+ unsigned BlockIntrospection: 1; // block have ObjC type encodings.
unsigned EmitAllDecls : 1; // Emit all declarations, even if
// they are unused.
unsigned MathErrno : 1; // Math functions must respect errno
@@ -83,6 +84,7 @@ public:
unsigned AccessControl : 1; // Whether C++ access control should
// be enabled.
unsigned CharIsSigned : 1; // Whether char is a signed or unsigned type
+ unsigned ShortWChar : 1; // Force wchar_t to be unsigned short int.
unsigned OpenCL : 1; // OpenCL C99 language extensions.
@@ -125,7 +127,8 @@ public:
ObjCConstantStringClass = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = 0;
- Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0;
+ Exceptions = Freestanding = NoBuiltin = 0;
+ NeXTRuntime = 1;
Rtti = 1;
LaxVectorConversions = 1;
HeinousExtensions = 0;
@@ -137,6 +140,7 @@ public:
ThreadsafeStatics = 0;
POSIXThreads = 0;
Blocks = 0;
+ BlockIntrospection = 0;
EmitAllDecls = 0;
MathErrno = 1;
@@ -159,6 +163,7 @@ public:
NoInline = 0;
CharIsSigned = 1;
+ ShortWChar = 0;
MainFileName = 0;
}
diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile
index 6ed5fefb7e64..b85eb0725ef0 100644
--- a/include/clang/Basic/Makefile
+++ b/include/clang/Basic/Makefile
@@ -9,12 +9,14 @@ TABLEGEN_INC_FILES_COMMON = 1
include $(LEVEL)/Makefile.common
+INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td)
+
$(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN)
$(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 $(wildcard Diagnostic*.td) $(TBLGEN)
+$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN)
$(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/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index e61ef9265cfb..695f51d2c4c9 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -28,11 +28,12 @@ class StringRef;
}
namespace clang {
-
class Diagnostic;
+class LangOptions;
class SourceLocation;
class SourceManager;
-class LangOptions;
+class TargetOptions;
+
namespace Builtin { struct Info; }
/// TargetInfo - This class exposes information about the current target.
@@ -44,16 +45,12 @@ protected:
// values are specified by the TargetInfo constructor.
bool TLSSupported;
unsigned char PointerWidth, PointerAlign;
- unsigned char WCharWidth, WCharAlign;
- unsigned char Char16Width, Char16Align;
- unsigned char Char32Width, Char32Align;
unsigned char IntWidth, IntAlign;
unsigned char FloatWidth, FloatAlign;
unsigned char DoubleWidth, DoubleAlign;
unsigned char LongDoubleWidth, LongDoubleAlign;
unsigned char LongWidth, LongAlign;
unsigned char LongLongWidth, LongLongAlign;
- unsigned char IntMaxTWidth;
const char *DescriptionString;
const char *UserLabelPrefix;
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
@@ -63,9 +60,9 @@ protected:
TargetInfo(const std::string &T);
public:
- /// CreateTargetInfo - Return the target info object for the specified target
- /// triple.
- static TargetInfo* CreateTargetInfo(const std::string &Triple);
+ /// CreateTargetInfo - Construct a target for the given options.
+ static TargetInfo* CreateTargetInfo(Diagnostic &Diags,
+ const TargetOptions &Opts);
virtual ~TargetInfo();
@@ -103,6 +100,10 @@ public:
/// enum. For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
+ /// getTypeAlign - Return the alignment (in bits) of the specified integer
+ /// type enum. For example, SignedInt -> getIntAlign().
+ unsigned getTypeAlign(IntType T) const;
+
/// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
bool isTypeSigned(IntType T) const;
@@ -146,18 +147,18 @@ public:
/// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in
/// bits.
- unsigned getWCharWidth() const { return WCharWidth; }
- unsigned getWCharAlign() const { return WCharAlign; }
+ unsigned getWCharWidth() const { return getTypeWidth(WCharType); }
+ unsigned getWCharAlign() const { return getTypeAlign(WCharType); }
/// getChar16Width/Align - Return the size of 'char16_t' for this target, in
/// bits.
- unsigned getChar16Width() const { return Char16Width; }
- unsigned getChar16Align() const { return Char16Align; }
+ unsigned getChar16Width() const { return getTypeWidth(Char16Type); }
+ unsigned getChar16Align() const { return getTypeAlign(Char16Type); }
/// getChar32Width/Align - Return the size of 'char32_t' for this target, in
/// bits.
- unsigned getChar32Width() const { return Char32Width; }
- unsigned getChar32Align() const { return Char32Align; }
+ unsigned getChar32Width() const { return getTypeWidth(Char32Type); }
+ unsigned getChar32Align() const { return getTypeAlign(Char32Type); }
/// getFloatWidth/Align/Format - Return the size/align/format of 'float'.
unsigned getFloatWidth() const { return FloatWidth; }
@@ -180,7 +181,7 @@ public:
/// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
/// target, in bits.
unsigned getIntMaxTWidth() const {
- return IntMaxTWidth;
+ return getTypeWidth(IntMaxType);
}
/// getUserLabelPrefix - This returns the default value of the
@@ -341,10 +342,10 @@ public:
return "";
}
- /// getDefaultLangOptions - Allow the target to specify default settings for
- /// various language options. These may be overridden by command line
- /// options.
- virtual void getDefaultLangOptions(LangOptions &Opts) {}
+ /// setForcedLangOptions - Set forced language options.
+ /// Apply changes to the target information with respect to certain
+ /// language options which change the target configuration.
+ virtual void setForcedLangOptions(LangOptions &Opts);
/// getDefaultFeatures - Get the default set of target features for
/// the \args CPU; this should include all legal feature strings on
@@ -375,9 +376,10 @@ public:
return false;
}
- /// HandleTargetOptions - Perform initialization based on the user
- /// configured set of features.
- virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features) {
+ /// HandleTargetOptions - Perform initialization based on the user configured
+ /// set of features (e.g., +sse4). The list is guaranteed to have at most one
+ /// entry per feature.
+ virtual void HandleTargetFeatures(const std::vector<std::string> &Features) {
}
// getRegParmMax - Returns maximal number of args passed in registers.
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
new file mode 100644
index 000000000000..eeaab1558fd1
--- /dev/null
+++ b/include/clang/Basic/TargetOptions.h
@@ -0,0 +1,39 @@
+//===--- TargetOptions.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
+#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// TargetOptions - Options for controlling the target.
+class TargetOptions {
+public:
+
+ /// If given, the name of the target triple to compile for. If not given the
+ /// target will be selected to match the host.
+ std::string Triple;
+
+ /// If given, the name of the target CPU to generate code for.
+ std::string CPU;
+
+ /// If given, the name of the target ABI to use.
+ std::string ABI;
+
+ /// The list of target specific features to enable or disable -- this should
+ /// be a list of strings starting with by '+' or '-'.
+ std::vector<std::string> Features;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h
new file mode 100644
index 000000000000..02679cd99895
--- /dev/null
+++ b/include/clang/CodeGen/CodeGenOptions.h
@@ -0,0 +1,75 @@
+//===--- CodeGenOptions.h ---------------------------------------*- 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 CodeGenOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H
+#define LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// CodeGenOptions - Track various options which control how the code
+/// is optimized and passed to the backend.
+class CodeGenOptions {
+public:
+ enum InliningMethod {
+ NoInlining, // Perform no inlining whatsoever.
+ NormalInlining, // Use the standard function inlining pass.
+ OnlyAlwaysInlining // Only run the always inlining pass.
+ };
+
+ unsigned DebugInfo : 1; /// Should generate deubg info (-g).
+ unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in
+ /// getting .bc files that correspond to the
+ /// internal state before optimizations are
+ /// done.
+ unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
+ unsigned MergeAllConstants : 1; /// Merge identical constants.
+ unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
+ unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
+ unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
+ unsigned OptimizeSize : 1; /// If -Os is specified.
+ unsigned SimplifyLibCalls : 1; /// Should standard library calls be treated
+ /// specially.
+ unsigned TimePasses : 1; /// Set when -ftime-report is enabled.
+ unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization
+ /// selection.
+ unsigned UnrollLoops : 1; /// Control whether loops are unrolled.
+ unsigned VerifyModule : 1; /// Control whether the module should be run
+ /// through the LLVM Verifier.
+
+ /// Inlining - The kind of inlining to perform.
+ InliningMethod Inlining;
+
+public:
+ CodeGenOptions() {
+ OptimizationLevel = 0;
+ OptimizeSize = 0;
+ DebugInfo = 0;
+ UnitAtATime = 1;
+ SimplifyLibCalls = UnrollLoops = 0;
+ VerifyModule = 1;
+ TimePasses = 0;
+ NoCommon = 0;
+ Inlining = NoInlining;
+ DisableRedZone = 0;
+ NoImplicitFloat = 0;
+ MergeAllConstants = 1;
+ DisableLLVMOpts = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h
index 1871c8f206f3..2a3aa6a90404 100644
--- a/include/clang/CodeGen/ModuleBuilder.h
+++ b/include/clang/CodeGen/ModuleBuilder.h
@@ -25,7 +25,7 @@ namespace llvm {
namespace clang {
class Diagnostic;
class LangOptions;
- class CompileOptions;
+ class CodeGenOptions;
class CodeGenerator : public ASTConsumer {
public:
@@ -35,7 +35,7 @@ namespace clang {
CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags,
const std::string &ModuleName,
- const CompileOptions &CO,
+ const CodeGenOptions &CGO,
llvm::LLVMContext& C);
}
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index c0327a2f1d1c..d3ab1153371a 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -48,7 +48,7 @@ class Driver {
public:
// Diag - Forwarding function for diagnostics.
DiagnosticBuilder Diag(unsigned DiagID) const {
- return Diags.Report(FullSourceLoc(), DiagID);
+ return Diags.Report(DiagID);
}
// FIXME: Privatize once interface is stable.
diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def
index 5370114ee824..2b66b3506b01 100644
--- a/include/clang/Driver/Options.def
+++ b/include/clang/Driver/Options.def
@@ -368,6 +368,7 @@ OPTION("-fastcp", fastcp, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fastf", fastf, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fast", fast, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fasynchronous-unwind-tables", fasynchronous_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fblock-introspection", fblock_introspection, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fblocks", fblocks, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fbootclasspath=", fbootclasspath_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fbuiltin-strcat", fbuiltin_strcat, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -430,6 +431,7 @@ OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0
OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-merge-all-constants", fno_merge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-ms-extensions", fno_ms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-omit-frame-pointer", fno_omit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-rtti", fno_rtti, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -448,7 +450,6 @@ OPTION("-fobjc-gc", fobjc_gc, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fobjc-new-property", fobjc_new_property, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fobjc-nonfragile-abi", fobjc_nonfragile_abi, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fobjc-sender-dependent-dispatch", fobjc_sender_dependent_dispatch, Flag, f_Group, INVALID, "", 0, 0, 0)
-OPTION("-fobjc-tight-layout", fobjc_tight_layout, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fobjc", fobjc, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fomit-frame-pointer", fomit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fopenmp", fopenmp, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -463,6 +464,7 @@ OPTION("-fprofile-arcs", fprofile_arcs, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fprofile-generate", fprofile_generate, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
OPTION("-frtti", frtti, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fshort-wchar", fshort_wchar, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0)
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index b7630d8afdb8..df651a6c3d00 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -90,6 +90,17 @@ public:
/// default.
virtual bool IsMathErrnoDefault() const = 0;
+ /// IsBlocksDefault - Does this tool chain enable -fblocks by default.
+ virtual bool IsBlocksDefault() const { return false; }
+
+ /// IsObjCNonFragileABIDefault - Does this tool chain set
+ /// -fobjc-nonfragile-abi by default.
+ virtual bool IsObjCNonFragileABIDefault() const { return false; }
+
+ /// GetDefaultStackProtectorLevel - Get the default stack protector level for
+ /// this tool chain (0=off, 1=on, 2=all).
+ virtual unsigned GetDefaultStackProtectorLevel() const { return 0; }
+
/// IsUnwindTablesDefault - Does this tool chain use -funwind-tables
/// by default.
virtual bool IsUnwindTablesDefault() const = 0;
diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
index 92520a77b33b..3a343b385e7a 100644
--- a/include/clang/Driver/Types.h
+++ b/include/clang/Driver/Types.h
@@ -62,6 +62,9 @@ namespace types {
/// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
bool isCXX(ID Id);
+ /// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
+ bool isObjC(ID Id);
+
/// lookupTypeForExtension - Lookup the type to use for the file
/// extension \arg Ext.
ID lookupTypeForExtension(const char *Ext);
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index 742813c66907..0e7d55e6e45b 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -25,11 +25,12 @@ namespace llvm {
namespace clang {
class ASTConsumer;
+class CodeGenOptions;
class Diagnostic;
class FileManager;
-class Preprocessor;
-class CompileOptions;
class LangOptions;
+class Preprocessor;
+class TargetOptions;
// AST pretty-printer: prints out the AST in a format that is close to the
// original C code. The output is intended to be in a format such that
@@ -69,7 +70,7 @@ ASTConsumer *CreateObjCRewriter(const std::string &InFile,
bool SilenceRewriteMacroWarning);
// LLVM code generator: uses the code generation backend to generate LLVM
-// assembly. This runs optimizations depending on the CompileOptions
+// assembly. This runs optimizations depending on the CodeGenOptions
// parameter. The output depends on the Action parameter.
enum BackendAction {
Backend_EmitAssembly, // Emit native assembly
@@ -80,7 +81,8 @@ enum BackendAction {
ASTConsumer *CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &Features,
- const CompileOptions &CompileOpts,
+ const CodeGenOptions &CodeGenOpts,
+ const TargetOptions &TargetOpts,
const std::string &ModuleID,
llvm::raw_ostream *OS,
llvm::LLVMContext& C);
diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def
index d5e408020a98..7d55673a612f 100644
--- a/include/clang/Frontend/Analyses.def
+++ b/include/clang/Frontend/Analyses.def
@@ -48,6 +48,9 @@ ANALYSIS(WarnObjCUnusedIvars, "warn-objc-unused-ivars",
ANALYSIS(CheckerCFRef, "checker-cfref",
"Run the [Core] Foundation reference count checker", Code)
+ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer",
+ "Warn about unintended use of sizeof() on pointer expressions", Code)
+
ANALYSIS(InlineCall, "inline-call",
"Experimental transfer function inling callees when its definition"
" is available.", TranslationUnit)
diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h
index 34054a7aa00e..7a324331ecdc 100644
--- a/include/clang/Frontend/AnalysisConsumer.h
+++ b/include/clang/Frontend/AnalysisConsumer.h
@@ -1,4 +1,4 @@
-//===--- AnalysisConsumer.h - Front-end hooks for the analysis engine------===//
+//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,9 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H
+#define LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H
+
#include <string>
#include <vector>
@@ -50,19 +53,37 @@ enum AnalysisDiagClients {
NUM_ANALYSIS_DIAG_CLIENTS
};
-struct AnalyzerOptions {
+class AnalyzerOptions {
+public:
std::vector<Analyses> AnalysisList;
AnalysisStores AnalysisStoreOpt;
AnalysisConstraints AnalysisConstraintsOpt;
AnalysisDiagClients AnalysisDiagOpt;
- bool VisualizeEGDot;
- bool VisualizeEGUbi;
- bool AnalyzeAll;
- bool AnalyzerDisplayProgress;
- bool PurgeDead;
- bool EagerlyAssume;
std::string AnalyzeSpecificFunction;
- bool TrimGraph;
+ unsigned AnalyzeAll : 1;
+ unsigned AnalyzerDisplayProgress : 1;
+ unsigned EagerlyAssume : 1;
+ unsigned PurgeDead : 1;
+ unsigned TrimGraph : 1;
+ unsigned VisualizeEGDot : 1;
+ unsigned VisualizeEGUbi : 1;
+ unsigned EnableExperimentalChecks : 1;
+ unsigned EnableExperimentalInternalChecks : 1;
+public:
+ AnalyzerOptions() {
+ AnalysisStoreOpt = BasicStoreModel;
+ AnalysisConstraintsOpt = RangeConstraintsModel;
+ AnalysisDiagOpt = PD_HTML;
+ AnalyzeAll = 0;
+ AnalyzerDisplayProgress = 0;
+ EagerlyAssume = 0;
+ PurgeDead = 0;
+ TrimGraph = 0;
+ VisualizeEGDot = 0;
+ VisualizeEGUbi = 0;
+ EnableExperimentalChecks = 0;
+ EnableExperimentalInternalChecks = 0;
+ }
};
/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
@@ -73,3 +94,5 @@ ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp,
const AnalyzerOptions& Opts);
}
+
+#endif
diff --git a/include/clang/Frontend/ChainedDiagnosticClient.h b/include/clang/Frontend/ChainedDiagnosticClient.h
new file mode 100644
index 000000000000..2d5e128dac37
--- /dev/null
+++ b/include/clang/Frontend/ChainedDiagnosticClient.h
@@ -0,0 +1,58 @@
+//===--- ChainedDiagnosticClient.h - Chain Diagnostic Clients ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H
+#define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+class LangOptions;
+
+/// ChainedDiagnosticClient - Chain two diagnostic clients so that diagnostics
+/// go to the first client and then the second. The first diagnostic client
+/// should be the "primary" client, and will be used for computing whether the
+/// diagnostics should be included in counts.
+class ChainedDiagnosticClient : public DiagnosticClient {
+ llvm::OwningPtr<DiagnosticClient> Primary;
+ llvm::OwningPtr<DiagnosticClient> Secondary;
+
+public:
+ ChainedDiagnosticClient(DiagnosticClient *_Primary,
+ DiagnosticClient *_Secondary) {
+ Primary.reset(_Primary);
+ Secondary.reset(_Secondary);
+ }
+
+ virtual void BeginSourceFile(const LangOptions &LO,
+ const Preprocessor *PP) {
+ Primary->BeginSourceFile(LO, PP);
+ Secondary->BeginSourceFile(LO, PP);
+ }
+
+ virtual void EndSourceFile() {
+ Secondary->EndSourceFile();
+ Primary->EndSourceFile();
+ }
+
+ virtual bool IncludeInDiagnosticCounts() const {
+ return Primary->IncludeInDiagnosticCounts();
+ }
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ Primary->HandleDiagnostic(DiagLevel, Info);
+ Secondary->HandleDiagnostic(DiagLevel, Info);
+ }
+};
+
+} // end namspace clang
+
+#endif
diff --git a/include/clang/Frontend/CommandLineSourceLoc.h b/include/clang/Frontend/CommandLineSourceLoc.h
index 59f70ede9129..d5a0598dfab2 100644
--- a/include/clang/Frontend/CommandLineSourceLoc.h
+++ b/include/clang/Frontend/CommandLineSourceLoc.h
@@ -1,3 +1,4 @@
+
//===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
@@ -37,7 +38,7 @@ namespace llvm {
class parser<clang::ParsedSourceLocation>
: public basic_parser<clang::ParsedSourceLocation> {
public:
- bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
+ inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
clang::ParsedSourceLocation &Val);
};
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
new file mode 100644
index 000000000000..ed280508778a
--- /dev/null
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -0,0 +1,523 @@
+//===-- CompilerInstance.h - Clang Compiler Instance ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
+#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
+
+#include "clang/Frontend/CompilerInvocation.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <cassert>
+#include <list>
+#include <string>
+
+namespace llvm {
+class LLVMContext;
+class raw_ostream;
+class raw_fd_ostream;
+}
+
+namespace clang {
+class ASTContext;
+class ASTConsumer;
+class CodeCompleteConsumer;
+class Diagnostic;
+class DiagnosticClient;
+class ExternalASTSource;
+class FileManager;
+class Preprocessor;
+class Source;
+class SourceManager;
+class TargetInfo;
+
+/// CompilerInstance - Helper class for managing a single instance of the Clang
+/// compiler.
+///
+/// The CompilerInstance serves two purposes:
+/// (1) It manages the various objects which are necessary to run the compiler,
+/// for example the preprocessor, the target information, and the AST
+/// context.
+/// (2) It provides utility routines for constructing and manipulating the
+/// common Clang objects.
+///
+/// The compiler instance generally owns the instance of all the objects that it
+/// manages. However, clients can still share objects by manually setting the
+/// object and retaking ownership prior to destroying the CompilerInstance.
+///
+/// The compiler instance is intended to simplify clients, but not to lock them
+/// in to the compiler instance for everything. When possible, utility functions
+/// come in two forms; a short form that reuses the CompilerInstance objects,
+/// and a long form that takes explicit instances of any required objects.
+class CompilerInstance {
+ /// The LLVM context used for this instance.
+ llvm::LLVMContext *LLVMContext;
+ bool OwnsLLVMContext;
+
+ /// The options used in this compiler instance.
+ CompilerInvocation Invocation;
+
+ /// The diagnostics engine instance.
+ llvm::OwningPtr<Diagnostic> Diagnostics;
+
+ /// The diagnostics client instance.
+ llvm::OwningPtr<DiagnosticClient> DiagClient;
+
+ /// The target being compiled for.
+ llvm::OwningPtr<TargetInfo> Target;
+
+ /// The file manager.
+ llvm::OwningPtr<FileManager> FileMgr;
+
+ /// The source manager.
+ llvm::OwningPtr<SourceManager> SourceMgr;
+
+ /// The preprocessor.
+ llvm::OwningPtr<Preprocessor> PP;
+
+ /// The AST context.
+ llvm::OwningPtr<ASTContext> Context;
+
+ /// The AST consumer.
+ llvm::OwningPtr<ASTConsumer> Consumer;
+
+ /// The code completion consumer.
+ llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer;
+
+ /// The list of active output files.
+ std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
+
+public:
+ /// Create a new compiler instance with the given LLVM context, optionally
+ /// taking ownership of it.
+ CompilerInstance(llvm::LLVMContext *_LLVMContext = 0,
+ bool _OwnsLLVMContext = true);
+ ~CompilerInstance();
+
+ /// @name LLVM Context
+ /// {
+
+ bool hasLLVMContext() const { return LLVMContext != 0; }
+
+ llvm::LLVMContext &getLLVMContext() const {
+ assert(LLVMContext && "Compiler instance has no LLVM context!");
+ return *LLVMContext;
+ }
+
+ /// setLLVMContext - Replace the current LLVM context and take ownership of
+ /// \arg Value.
+ void setLLVMContext(llvm::LLVMContext *Value, bool TakeOwnership = true) {
+ LLVMContext = Value;
+ OwnsLLVMContext = TakeOwnership;
+ }
+
+ /// }
+ /// @name Compiler Invocation and Options
+ /// {
+
+ CompilerInvocation &getInvocation() { return Invocation; }
+ const CompilerInvocation &getInvocation() const { return Invocation; }
+ void setInvocation(const CompilerInvocation &Value) { Invocation = Value; }
+
+ /// }
+ /// @name Forwarding Methods
+ /// {
+
+ AnalyzerOptions &getAnalyzerOpts() {
+ return Invocation.getAnalyzerOpts();
+ }
+ const AnalyzerOptions &getAnalyzerOpts() const {
+ return Invocation.getAnalyzerOpts();
+ }
+
+ CodeGenOptions &getCodeGenOpts() {
+ return Invocation.getCodeGenOpts();
+ }
+ const CodeGenOptions &getCodeGenOpts() const {
+ return Invocation.getCodeGenOpts();
+ }
+
+ DependencyOutputOptions &getDependencyOutputOpts() {
+ return Invocation.getDependencyOutputOpts();
+ }
+ const DependencyOutputOptions &getDependencyOutputOpts() const {
+ return Invocation.getDependencyOutputOpts();
+ }
+
+ DiagnosticOptions &getDiagnosticOpts() {
+ return Invocation.getDiagnosticOpts();
+ }
+ const DiagnosticOptions &getDiagnosticOpts() const {
+ return Invocation.getDiagnosticOpts();
+ }
+
+ FrontendOptions &getFrontendOpts() {
+ return Invocation.getFrontendOpts();
+ }
+ const FrontendOptions &getFrontendOpts() const {
+ return Invocation.getFrontendOpts();
+ }
+
+ HeaderSearchOptions &getHeaderSearchOpts() {
+ return Invocation.getHeaderSearchOpts();
+ }
+ const HeaderSearchOptions &getHeaderSearchOpts() const {
+ return Invocation.getHeaderSearchOpts();
+ }
+
+ LangOptions &getLangOpts() {
+ return Invocation.getLangOpts();
+ }
+ const LangOptions &getLangOpts() const {
+ return Invocation.getLangOpts();
+ }
+
+ PreprocessorOptions &getPreprocessorOpts() {
+ return Invocation.getPreprocessorOpts();
+ }
+ const PreprocessorOptions &getPreprocessorOpts() const {
+ return Invocation.getPreprocessorOpts();
+ }
+
+ PreprocessorOutputOptions &getPreprocessorOutputOpts() {
+ return Invocation.getPreprocessorOutputOpts();
+ }
+ const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
+ return Invocation.getPreprocessorOutputOpts();
+ }
+
+ TargetOptions &getTargetOpts() {
+ return Invocation.getTargetOpts();
+ }
+ const TargetOptions &getTargetOpts() const {
+ return Invocation.getTargetOpts();
+ }
+
+ /// }
+ /// @name Diagnostics Engine
+ /// {
+
+ bool hasDiagnostics() const { return Diagnostics != 0; }
+
+ Diagnostic &getDiagnostics() const {
+ assert(Diagnostics && "Compiler instance has no diagnostics!");
+ return *Diagnostics;
+ }
+
+ /// takeDiagnostics - Remove the current diagnostics engine and give ownership
+ /// to the caller.
+ Diagnostic *takeDiagnostics() { return Diagnostics.take(); }
+
+ /// setDiagnostics - Replace the current diagnostics engine; the compiler
+ /// instance takes ownership of \arg Value.
+ void setDiagnostics(Diagnostic *Value);
+
+ DiagnosticClient &getDiagnosticClient() const {
+ assert(Target && "Compiler instance has no diagnostic client!");
+ return *DiagClient;
+ }
+
+ /// takeDiagnosticClient - Remove the current diagnostics client and give
+ /// ownership to the caller.
+ DiagnosticClient *takeDiagnosticClient() { return DiagClient.take(); }
+
+ /// setDiagnosticClient - Replace the current diagnostics client; the compiler
+ /// instance takes ownership of \arg Value.
+ void setDiagnosticClient(DiagnosticClient *Value);
+
+ /// }
+ /// @name Target Info
+ /// {
+
+ bool hasTarget() const { return Target != 0; }
+
+ TargetInfo &getTarget() const {
+ assert(Target && "Compiler instance has no target!");
+ return *Target;
+ }
+
+ /// takeTarget - Remove the current diagnostics engine and give ownership
+ /// to the caller.
+ TargetInfo *takeTarget() { return Target.take(); }
+
+ /// setTarget - Replace the current diagnostics engine; the compiler
+ /// instance takes ownership of \arg Value.
+ void setTarget(TargetInfo *Value);
+
+ /// }
+ /// @name File Manager
+ /// {
+
+ bool hasFileManager() const { return FileMgr != 0; }
+
+ FileManager &getFileManager() const {
+ assert(FileMgr && "Compiler instance has no file manager!");
+ return *FileMgr;
+ }
+
+ /// takeFileManager - Remove the current file manager and give ownership to
+ /// the caller.
+ FileManager *takeFileManager() { return FileMgr.take(); }
+
+ /// setFileManager - Replace the current file manager; the compiler instance
+ /// takes ownership of \arg Value.
+ void setFileManager(FileManager *Value);
+
+ /// }
+ /// @name Source Manager
+ /// {
+
+ bool hasSourceManager() const { return SourceMgr != 0; }
+
+ SourceManager &getSourceManager() const {
+ assert(SourceMgr && "Compiler instance has no source manager!");
+ return *SourceMgr;
+ }
+
+ /// takeSourceManager - Remove the current source manager and give ownership
+ /// to the caller.
+ SourceManager *takeSourceManager() { return SourceMgr.take(); }
+
+ /// setSourceManager - Replace the current source manager; the compiler
+ /// instance takes ownership of \arg Value.
+ void setSourceManager(SourceManager *Value);
+
+ /// }
+ /// @name Preprocessor
+ /// {
+
+ bool hasPreprocessor() const { return PP != 0; }
+
+ Preprocessor &getPreprocessor() const {
+ assert(PP && "Compiler instance has no preprocessor!");
+ return *PP;
+ }
+
+ /// takePreprocessor - Remove the current preprocessor and give ownership to
+ /// the caller.
+ Preprocessor *takePreprocessor() { return PP.take(); }
+
+ /// setPreprocessor - Replace the current preprocessor; the compiler instance
+ /// takes ownership of \arg Value.
+ void setPreprocessor(Preprocessor *Value);
+
+ /// }
+ /// @name ASTContext
+ /// {
+
+ bool hasASTContext() const { return Context != 0; }
+
+ ASTContext &getASTContext() const {
+ assert(Context && "Compiler instance has no AST context!");
+ return *Context;
+ }
+
+ /// takeASTContext - Remove the current AST context and give ownership to the
+ /// caller.
+ ASTContext *takeASTContext() { return Context.take(); }
+
+ /// setASTContext - Replace the current AST context; the compiler instance
+ /// takes ownership of \arg Value.
+ void setASTContext(ASTContext *Value);
+
+ /// }
+ /// @name ASTConsumer
+ /// {
+
+ bool hasASTConsumer() const { return Consumer != 0; }
+
+ ASTConsumer &getASTConsumer() const {
+ assert(Consumer && "Compiler instance has no AST consumer!");
+ return *Consumer;
+ }
+
+ /// takeASTConsumer - Remove the current AST consumer and give ownership to
+ /// the caller.
+ ASTConsumer *takeASTConsumer() { return Consumer.take(); }
+
+ /// setASTConsumer - Replace the current AST consumer; the compiler instance
+ /// takes ownership of \arg Value.
+ void setASTConsumer(ASTConsumer *Value);
+
+ /// }
+ /// @name Code Completion
+ /// {
+
+ bool hasCodeCompletionConsumer() const { return CompletionConsumer != 0; }
+
+ CodeCompleteConsumer &getCodeCompletionConsumer() const {
+ assert(CompletionConsumer &&
+ "Compiler instance has no code completion consumer!");
+ return *CompletionConsumer;
+ }
+
+ /// takeCodeCompletionConsumer - Remove the current code completion consumer
+ /// and give ownership to the caller.
+ CodeCompleteConsumer *takeCodeCompletionConsumer() {
+ return CompletionConsumer.take();
+ }
+
+ /// setCodeCompletionConsumer - Replace the current code completion consumer;
+ /// the compiler instance takes ownership of \arg Value.
+ void setCodeCompletionConsumer(CodeCompleteConsumer *Value);
+
+ /// }
+ /// @name Output Files
+ /// {
+
+ /// getOutputFileList - Get the list of (path, output stream) pairs of output
+ /// files; the path may be empty but the stream will always be non-null.
+ const std::list< std::pair<std::string,
+ llvm::raw_ostream*> > &getOutputFileList() const;
+
+ /// addOutputFile - Add an output file onto the list of tracked output files.
+ ///
+ /// \param Path - The path to the output file, or empty.
+ /// \param OS - The output stream, which should be non-null.
+ void addOutputFile(llvm::StringRef Path, llvm::raw_ostream *OS);
+
+ /// ClearOutputFiles - Clear the output file list, destroying the contained
+ /// output streams.
+ ///
+ /// \param EraseFiles - If true, attempt to erase the files from disk.
+ void ClearOutputFiles(bool EraseFiles);
+
+ /// }
+ /// @name Construction Utility Methods
+ /// {
+
+ /// Create the diagnostics engine using the invocation's diagnostic options
+ /// and replace any existing one with it.
+ ///
+ /// Note that this routine also replaces the diagnostic client.
+ void createDiagnostics(int Argc, char **Argv);
+
+ /// Create a Diagnostic object with a the TextDiagnosticPrinter.
+ ///
+ /// The \arg Argc and \arg Argv arguments are used only for logging purposes,
+ /// when the diagnostic options indicate that the compiler should output
+ /// logging information.
+ ///
+ /// Note that this creates an unowned DiagnosticClient, if using directly the
+ /// caller is responsible for releaseing the returned Diagnostic's client
+ /// eventually.
+ ///
+ /// \return The new object on success, or null on failure.
+ static Diagnostic *createDiagnostics(const DiagnosticOptions &Opts,
+ int Argc, char **Argv);
+
+ /// Create the file manager and replace any existing one with it.
+ void createFileManager();
+
+ /// Create the source manager and replace any existing one with it.
+ void createSourceManager();
+
+ /// Create the preprocessor, using the invocation, file, and source managers,
+ /// and replace any existing one with it.
+ void createPreprocessor();
+
+ /// Create a Preprocessor object.
+ ///
+ /// Note that this also creates a new HeaderSearch object which will be owned
+ /// by the resulting Preprocessor.
+ ///
+ /// \return The new object on success, or null on failure.
+ static Preprocessor *createPreprocessor(Diagnostic &, const LangOptions &,
+ const PreprocessorOptions &,
+ const HeaderSearchOptions &,
+ const DependencyOutputOptions &,
+ const TargetInfo &,
+ SourceManager &, FileManager &);
+
+ /// Create the AST context.
+ void createASTContext();
+
+ /// Create an external AST source to read a PCH file and attach it to the AST
+ /// context.
+ void createPCHExternalASTSource(llvm::StringRef Path);
+
+ /// Create an external AST source to read a PCH file.
+ ///
+ /// \return - The new object on success, or null on failure.
+ static ExternalASTSource *
+ createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
+ Preprocessor &PP, ASTContext &Context);
+
+ /// Create a code completion consumer using the invocation; note that this
+ /// will cause the source manager to truncate the input source file at the
+ /// completion point.
+ void createCodeCompletionConsumer();
+
+ /// Create a code completion consumer to print code completion results, at
+ /// \arg Filename, \arg Line, and \arg Column, to the given output stream \arg
+ /// OS.
+ static CodeCompleteConsumer *
+ createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
+ unsigned Line, unsigned Column,
+ bool UseDebugPrinter, bool ShowMacros,
+ llvm::raw_ostream &OS);
+
+ /// Create the default output file (from the invocation's options) and add it
+ /// to the list of tracked output files.
+ llvm::raw_fd_ostream *
+ createDefaultOutputFile(bool Binary = true, llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "");
+
+ /// Create a new output file and add it to the list of tracked output files,
+ /// optionally deriving the output path name.
+ llvm::raw_fd_ostream *
+ createOutputFile(llvm::StringRef OutputPath, bool Binary = true,
+ llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "");
+
+ /// Create a new output file, optionally deriving the output path name.
+ ///
+ /// If \arg OutputPath is empty, then createOutputFile will derive an output
+ /// path location as \arg BaseInput, with any suffix removed, and \arg
+ /// Extension appended.
+ ///
+ /// \param OutputPath - If given, the path to the output file.
+ /// \param Error [out] - On failure, the error message.
+ /// \param BaseInput - If \arg OutputPath is empty, the input path name to use
+ /// for deriving the output path.
+ /// \param Extension - The extension to use for derived output names.
+ /// \param Binary - The mode to open the file in.
+ /// \param ResultPathName [out] - If given, the result path name will be
+ /// stored here on success.
+ static llvm::raw_fd_ostream *
+ createOutputFile(llvm::StringRef OutputPath, std::string &Error,
+ bool Binary = true, llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "",
+ std::string *ResultPathName = 0);
+
+ /// }
+ /// @name Initialization Utility Methods
+ /// {
+
+ /// InitializeSourceManager - Initialize the source manager to set InputFile
+ /// as the main file.
+ ///
+ /// \return True on success.
+ bool InitializeSourceManager(llvm::StringRef InputFile);
+
+ /// InitializeSourceManager - Initialize the source manager to set InputFile
+ /// as the main file.
+ ///
+ /// \return True on success.
+ static bool InitializeSourceManager(llvm::StringRef InputFile,
+ Diagnostic &Diags,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ const FrontendOptions &Opts);
+
+ /// }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
new file mode 100644
index 000000000000..9d068c523c69
--- /dev/null
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -0,0 +1,150 @@
+//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
+#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
+#include "clang/Frontend/AnalysisConsumer.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Frontend/PreprocessorOptions.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+ template<typename T> class SmallVectorImpl;
+}
+
+namespace clang {
+
+/// CompilerInvocation - Helper class for holding the data necessary to invoke
+/// the compiler.
+///
+/// This class is designed to represent an abstract "invocation" of the
+/// compiler, including data such as the include paths, the code generation
+/// options, the warning flags, and so on.
+class CompilerInvocation {
+ /// Options controlling the static analyzer.
+ AnalyzerOptions AnalyzerOpts;
+
+ /// Options controlling IRgen and the backend.
+ CodeGenOptions CodeGenOpts;
+
+ /// Options controlling dependency output.
+ DependencyOutputOptions DependencyOutputOpts;
+
+ /// Options controlling the diagnostic engine.
+ DiagnosticOptions DiagnosticOpts;
+
+ /// Options controlling the frontend itself.
+ FrontendOptions FrontendOpts;
+
+ /// Options controlling the #include directive.
+ HeaderSearchOptions HeaderSearchOpts;
+
+ /// Options controlling the language variant.
+ LangOptions LangOpts;
+
+ /// Options controlling the preprocessor (aside from #include handling).
+ PreprocessorOptions PreprocessorOpts;
+
+ /// Options controlling preprocessed output.
+ PreprocessorOutputOptions PreprocessorOutputOpts;
+
+ /// Options controlling the target.
+ TargetOptions TargetOpts;
+
+public:
+ CompilerInvocation() {}
+
+ /// @name Utility Methods
+ /// @{
+
+ /// CreateFromArgs - Create a compiler invocation from a list of input
+ /// options.
+ ///
+ /// FIXME: Documenting error behavior.
+ ///
+ /// \param Res [out] - The resulting invocation.
+ /// \param Args - The input argument strings.
+ static void CreateFromArgs(CompilerInvocation &Res,
+ const llvm::SmallVectorImpl<llvm::StringRef> &Args);
+
+ /// toArgs - Convert the CompilerInvocation to a list of strings suitable for
+ /// passing to CreateFromArgs.
+ void toArgs(std::vector<std::string> &Res);
+
+ /// @}
+ /// @name Option Subgroups
+ /// @{
+
+ AnalyzerOptions &getAnalyzerOpts() { return AnalyzerOpts; }
+ const AnalyzerOptions &getAnalyzerOpts() const {
+ return AnalyzerOpts;
+ }
+
+ CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
+ const CodeGenOptions &getCodeGenOpts() const {
+ return CodeGenOpts;
+ }
+
+ DependencyOutputOptions &getDependencyOutputOpts() {
+ return DependencyOutputOpts;
+ }
+ const DependencyOutputOptions &getDependencyOutputOpts() const {
+ return DependencyOutputOpts;
+ }
+
+ DiagnosticOptions &getDiagnosticOpts() { return DiagnosticOpts; }
+ const DiagnosticOptions &getDiagnosticOpts() const { return DiagnosticOpts; }
+
+ HeaderSearchOptions &getHeaderSearchOpts() { return HeaderSearchOpts; }
+ const HeaderSearchOptions &getHeaderSearchOpts() const {
+ return HeaderSearchOpts;
+ }
+
+ FrontendOptions &getFrontendOpts() { return FrontendOpts; }
+ const FrontendOptions &getFrontendOpts() const {
+ return FrontendOpts;
+ }
+
+ LangOptions &getLangOpts() { return LangOpts; }
+ const LangOptions &getLangOpts() const { return LangOpts; }
+
+ PreprocessorOptions &getPreprocessorOpts() { return PreprocessorOpts; }
+ const PreprocessorOptions &getPreprocessorOpts() const {
+ return PreprocessorOpts;
+ }
+
+ PreprocessorOutputOptions &getPreprocessorOutputOpts() {
+ return PreprocessorOutputOpts;
+ }
+ const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
+ return PreprocessorOutputOpts;
+ }
+
+ TargetOptions &getTargetOpts() { return TargetOpts; }
+ const TargetOptions &getTargetOpts() const {
+ return TargetOpts;
+ }
+
+ /// @}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h
new file mode 100644
index 000000000000..ab8e49df9a88
--- /dev/null
+++ b/include/clang/Frontend/DependencyOutputOptions.h
@@ -0,0 +1,43 @@
+//===--- DependencyOutputOptions.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H
+#define LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// DependencyOutputOptions - Options for controlling the compiler dependency
+/// file generation.
+class DependencyOutputOptions {
+public:
+ unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies.
+ unsigned UsePhonyTargets : 1; ///< Include phony targets for each
+ /// dependency, which can avoid some 'make'
+ /// problems.
+
+ /// The file to write depencency output to.
+ std::string OutputFile;
+
+ /// A list of names to use as the targets in the dependency file; this list
+ /// must contain at least one entry.
+ std::vector<std::string> Targets;
+
+public:
+ DependencyOutputOptions() {
+ IncludeSystemHeaders = 0;
+ UsePhonyTargets = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
index 58673e4dad6b..6346dc0bfdec 100644
--- a/include/clang/Frontend/DiagnosticOptions.h
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -19,6 +19,10 @@ namespace clang {
/// engine.
class DiagnosticOptions {
public:
+ unsigned IgnoreWarnings : 1; /// -w
+ unsigned NoRewriteMacros : 1; /// -Wno-rewrite-macros
+ unsigned Pedantic : 1; /// -pedantic
+ unsigned PedanticErrors : 1; /// -pedantic-errors
unsigned ShowColumn : 1; /// Show column number on diagnostics.
unsigned ShowLocation : 1; /// Show source location information.
unsigned ShowCarets : 1; /// Show carets in diagnostics.
@@ -27,20 +31,36 @@ public:
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
/// diagnostics.
unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
+ unsigned VerifyDiagnostics; /// Check that diagnostics match the expected
+ /// diagnostics, indicated by markers in the
+ /// input source file.
/// Column limit for formatting message diagnostics, or 0 if unused.
unsigned MessageLength;
+ /// If non-empty, a file to log extended build information to, for development
+ /// testing and analysis.
+ std::string DumpBuildInformation;
+
+ /// The list of -W... options used to alter the diagnostic mappings, with the
+ /// prefixes removed.
+ std::vector<std::string> Warnings;
+
public:
DiagnosticOptions() {
- ShowColumn = 1;
- ShowLocation = 1;
+ IgnoreWarnings = 0;
+ MessageLength = 0;
+ NoRewriteMacros = 0;
+ Pedantic = 0;
+ PedanticErrors = 0;
ShowCarets = 1;
+ ShowColors = 0;
+ ShowColumn = 1;
ShowFixits = 1;
- ShowSourceRanges = 0;
+ ShowLocation = 1;
ShowOptionNames = 0;
- ShowColors = 0;
- MessageLength = 0;
+ ShowSourceRanges = 0;
+ VerifyDiagnostics = 0;
}
};
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
new file mode 100644
index 000000000000..469ea535f6aa
--- /dev/null
+++ b/include/clang/Frontend/FrontendAction.h
@@ -0,0 +1,215 @@
+//===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H
+#define LLVM_CLANG_FRONTEND_FRONTENDACTION_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <string>
+
+namespace llvm {
+class Timer;
+}
+
+namespace clang {
+class ASTUnit;
+class ASTConsumer;
+class CompilerInstance;
+
+/// FrontendAction - Abstract base class for actions which can be performed by
+/// the frontend.
+class FrontendAction {
+ std::string CurrentFile;
+ llvm::OwningPtr<ASTUnit> CurrentASTUnit;
+ CompilerInstance *Instance;
+ llvm::Timer *CurrentTimer;
+
+protected:
+ /// @name Implementation Action Interface
+ /// @{
+
+ /// CreateASTConsumer - Create the AST consumer object for this action, if
+ /// supported.
+ ///
+ /// This routine is called as part of \see BeginSourceAction(), which will
+ /// fail if the AST consumer cannot be created. This will not be called if the
+ /// action has indicated that it only uses the preprocessor.
+ ///
+ /// \param CI - The current compiler instance, provided as a convenience, \see
+ /// getCompilerInstance().
+ ///
+ /// \param InFile - The current input file, provided as a convenience, \see
+ /// getCurrentFile().
+ ///
+ /// \return The new AST consumer, or 0 on failure.
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) = 0;
+
+ /// BeginSourceFileAction - Callback at the start of processing a single
+ /// input.
+ ///
+ /// \return True on success; on failure \see ExecutionAction() and
+ /// EndSourceFileAction() will not be called.
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename) {
+ return true;
+ }
+
+ /// ExecuteAction - Callback to run the program action, using the initialized
+ /// compiler instance.
+ ///
+ /// This routine is guaranteed to only be called between \see
+ /// BeginSourceFileAction() and \see EndSourceFileAction().
+ virtual void ExecuteAction() = 0;
+
+ /// EndSourceFileAction - Callback at the end of processing a single input;
+ /// this is guaranteed to only be called following a successful call to
+ /// BeginSourceFileAction (and BeingSourceFile).
+ virtual void EndSourceFileAction() {}
+
+ /// @}
+
+public:
+ FrontendAction();
+ virtual ~FrontendAction();
+
+ /// @name Compiler Instance Access
+ /// @{
+
+ CompilerInstance &getCompilerInstance() const {
+ assert(Instance && "Compiler instance not registered!");
+ return *Instance;
+ }
+
+ void setCompilerInstance(CompilerInstance *Value) { Instance = Value; }
+
+ /// @}
+ /// @name Current File Information
+ /// @{
+
+ bool isCurrentFileAST() const {
+ assert(!CurrentFile.empty() && "No current file!");
+ return CurrentASTUnit != 0;
+ }
+
+ const std::string &getCurrentFile() const {
+ assert(!CurrentFile.empty() && "No current file!");
+ return CurrentFile;
+ }
+
+ ASTUnit &getCurrentASTUnit() const {
+ assert(!CurrentASTUnit && "No current AST unit!");
+ return *CurrentASTUnit;
+ }
+
+ void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0);
+
+ /// @}
+ /// @name Timing Utilities
+ /// @{
+
+ llvm::Timer *getCurrentTimer() const {
+ return CurrentTimer;
+ }
+
+ void setCurrentTimer(llvm::Timer *Value) {
+ CurrentTimer = Value;
+ }
+
+ /// @}
+ /// @name Supported Modes
+ /// @{
+
+ /// usesPreprocessorOnly - Does this action only use the preprocessor? If so
+ /// no AST context will be created and this action will be invalid with PCH
+ /// inputs.
+ virtual bool usesPreprocessorOnly() const = 0;
+
+ /// usesCompleteTranslationUnit - For AST based actions, should the
+ /// translation unit be completed?
+ virtual bool usesCompleteTranslationUnit() { return true; }
+
+ /// hasPCHSupport - Does this action support use with PCH?
+ virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); }
+
+ /// hasASTSupport - Does this action support use with AST files?
+ virtual bool hasASTSupport() const { return !usesPreprocessorOnly(); }
+
+ /// hasCodeCompletionSupport - Does this action support use with code
+ /// completion?
+ virtual bool hasCodeCompletionSupport() const { return false; }
+
+ /// @}
+ /// @name Public Action Interface
+ /// @{
+
+ /// BeginSourceFile - Prepare the action for processing the input file \arg
+ /// Filename; this is run after the options and frontend have been
+ /// initialized, but prior to executing any per-file processing.
+ ///
+ /// \param CI - The compiler instance this action is being run from. The
+ /// action may store and use this object up until the matching EndSourceFile
+ /// action.
+ ///
+ /// \param Filename - The input filename, which will be made available to
+ /// clients via \see getCurrentFile().
+ ///
+ /// \param IsAST - Indicates whether this is an AST input. AST inputs require
+ /// special handling, since the AST file itself contains several objects which
+ /// would normally be owned by the CompilerInstance. When processing AST input
+ /// files, these objects should generally not be initialized in the
+ /// CompilerInstance -- they will automatically be shared with the AST file in
+ /// between \see BeginSourceFile() and \see EndSourceFile().
+ ///
+ /// \return True on success; the compilation of this file should be aborted
+ /// and neither Execute nor EndSourceFile should be called.
+ bool BeginSourceFile(CompilerInstance &CI, llvm::StringRef Filename,
+ bool IsAST = false);
+
+ /// Execute - Set the source managers main input file, and run the action.
+ void Execute();
+
+ /// EndSourceFile - Perform any per-file post processing, deallocate per-file
+ /// objects, and run statistics and output file cleanup code.
+ void EndSourceFile();
+
+ /// @}
+};
+
+/// ASTFrontendAction - Abstract base class to use for AST consumer based
+/// frontend actios.
+class ASTFrontendAction : public FrontendAction {
+ /// ExecuteAction - Implement the ExecuteAction interface by running Sema on
+ /// the already initialized AST consumer.
+ ///
+ /// This will also take care of instantiating a code completion consumer if
+ /// the user requested it and the action supports it.
+ virtual void ExecuteAction();
+
+public:
+ virtual bool usesPreprocessorOnly() const { return false; }
+};
+
+/// PreprocessorFrontendAction - Abstract base class to use for preprocessor
+/// based frontend actions.
+class PreprocessorFrontendAction : public FrontendAction {
+protected:
+ /// CreateASTConsumer - Provide a default implementation which returns aborts,
+ /// this method should never be called by FrontendAction clients.
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+public:
+ virtual bool usesPreprocessorOnly() const { return true; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
new file mode 100644
index 000000000000..e755fe1b1b5f
--- /dev/null
+++ b/include/clang/Frontend/FrontendActions.h
@@ -0,0 +1,216 @@
+//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H
+#define LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H
+
+#include "clang/Frontend/FrontendAction.h"
+
+namespace clang {
+class FixItRewriter;
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class AnalysisAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTPrintAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTPrintXMLAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTDumpAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTViewAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class DeclContextPrintAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class DumpRecordAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class FixItAction : public ASTFrontendAction {
+private:
+ llvm::OwningPtr<FixItRewriter> Rewriter;
+
+protected:
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename);
+
+ virtual void EndSourceFileAction();
+
+ virtual bool hasASTSupport() const { return false; }
+
+public:
+ FixItAction();
+ ~FixItAction();
+};
+
+class GeneratePCHAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+ virtual bool usesCompleteTranslationUnit() { return false; }
+
+ virtual bool hasASTSupport() const { return false; }
+};
+
+class HTMLPrintAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class InheritanceViewAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class RewriteObjCAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class RewriteBlocksAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class SyntaxOnlyAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+public:
+ virtual bool hasCodeCompletionSupport() const { return true; }
+};
+
+//===----------------------------------------------------------------------===//
+// Code Gen AST Actions
+//===----------------------------------------------------------------------===//
+
+class CodeGenAction : public ASTFrontendAction {
+private:
+ unsigned Act;
+
+protected:
+ CodeGenAction(unsigned _Act);
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class EmitAssemblyAction : public CodeGenAction {
+public:
+ EmitAssemblyAction();
+};
+
+class EmitBCAction : public CodeGenAction {
+public:
+ EmitBCAction();
+};
+
+class EmitLLVMAction : public CodeGenAction {
+public:
+ EmitLLVMAction();
+};
+
+class EmitLLVMOnlyAction : public CodeGenAction {
+public:
+ EmitLLVMOnlyAction();
+};
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+class DumpRawTokensAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class DumpTokensAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class GeneratePTHAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class ParseOnlyAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class PreprocessOnlyAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class PrintParseAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class PrintPreprocessedAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+
+ virtual bool hasPCHSupport() const { return true; }
+};
+
+class RewriteMacrosAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class RewriteTestAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
new file mode 100644
index 000000000000..197a2a05e5e0
--- /dev/null
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -0,0 +1,131 @@
+//===--- FrontendOptions.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
+#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
+
+#include "clang/Frontend/CommandLineSourceLoc.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+
+namespace frontend {
+ enum ActionKind {
+ ASTDump, ///< Parse ASTs and dump them.
+ ASTPrint, ///< Parse ASTs and print them.
+ ASTPrintXML, ///< Parse ASTs and print them in XML.
+ ASTView, ///< Parse ASTs and view them in Graphviz.
+ DumpRawTokens, ///< Dump out raw tokens.
+ DumpRecordLayouts, ///< Dump record layout information.
+ DumpTokens, ///< Dump out preprocessed tokens.
+ EmitAssembly, ///< Emit a .s file.
+ EmitBC, ///< Emit a .bc file.
+ EmitHTML, ///< Translate input source into HTML.
+ EmitLLVM, ///< Emit a .ll file.
+ EmitLLVMOnly, ///< Generate LLVM IR, but do not
+ FixIt, ///< Parse and apply any fixits to the source.
+ GeneratePCH, ///< Generate pre-compiled header.
+ GeneratePTH, ///< Generate pre-tokenized header.
+ InheritanceView, ///< View C++ inheritance for a specified class.
+ ParseNoop, ///< Parse with noop callbacks.
+ ParsePrintCallbacks, ///< Parse and print each callback.
+ ParseSyntaxOnly, ///< Parse and perform semantic analysis.
+ PluginAction, ///< Run a plugin action, \see ActionName.
+ PrintDeclContext, ///< Print DeclContext and their Decls.
+ PrintPreprocessedInput, ///< -E mode.
+ RewriteBlocks, ///< ObjC->C Rewriter for Blocks.
+ RewriteMacros, ///< Expand macros but not #includes.
+ RewriteObjC, ///< ObjC->C Rewriter.
+ RewriteTest, ///< Rewriter playground
+ RunAnalysis, ///< Run one or more source code analyses.
+ RunPreprocessorOnly ///< Just lex, no output.
+ };
+}
+
+/// FrontendOptions - Options for controlling the behavior of the frontend.
+class FrontendOptions {
+public:
+ enum InputKind {
+ IK_None,
+ IK_Asm,
+ IK_C,
+ IK_CXX,
+ IK_ObjC,
+ IK_ObjCXX,
+ IK_PreprocessedC,
+ IK_PreprocessedCXX,
+ IK_PreprocessedObjC,
+ IK_PreprocessedObjCXX,
+ IK_OpenCL,
+ IK_AST
+ };
+
+ unsigned DebugCodeCompletionPrinter : 1; ///< Use the debug printer for code
+ /// completion results.
+ unsigned DisableFree : 1; ///< Disable memory freeing on exit.
+ unsigned EmptyInputOnly : 1; ///< Force input files to be treated
+ /// as if they were empty, for timing
+ /// the frontend startup.
+ unsigned RelocatablePCH : 1; ///< When generating PCH files,
+ /// instruct the PCH writer to create
+ /// relocatable PCH files.
+ unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion
+ /// results.
+ unsigned ShowStats : 1; ///< Show frontend performance
+ /// metrics and statistics.
+ unsigned ShowTimers : 1; ///< Show timers for individual
+ /// actions.
+
+ /// The input files and their types.
+ std::vector<std::pair<InputKind, std::string> > Inputs;
+
+ /// The output file, if any.
+ std::string OutputFile;
+
+ /// If given, the name for a C++ class to view the inheritance of.
+ std::string ViewClassInheritance;
+
+ /// A list of locations to apply fix-its at.
+ std::vector<ParsedSourceLocation> FixItLocations;
+
+ /// If given, enable code completion at the provided location.
+ ParsedSourceLocation CodeCompletionAt;
+
+ /// The frontend action to perform.
+ frontend::ActionKind ProgramAction;
+
+ /// The name of the action to run when using a plugin action.
+ std::string ActionName;
+
+public:
+ FrontendOptions() {
+ DebugCodeCompletionPrinter = 0;
+ DisableFree = 0;
+ EmptyInputOnly = 0;
+ ProgramAction = frontend::ParseSyntaxOnly;
+ ActionName = "";
+ RelocatablePCH = 0;
+ ShowMacrosInCodeCompletion = 0;
+ ShowStats = 0;
+ ShowTimers = 0;
+ }
+
+ /// getInputKindForExtension - Return the appropriate input kind for a file
+ /// extension. For example, "c" would return IK_C.
+ ///
+ /// \return The input kind for the extension, or IK_None if the extension is
+ /// not recognized.
+ static InputKind getInputKindForExtension(llvm::StringRef Extension);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h
new file mode 100644
index 000000000000..8341492cfd23
--- /dev/null
+++ b/include/clang/Frontend/FrontendPluginRegistry.h
@@ -0,0 +1,23 @@
+//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H
+#define LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+
+/// The frontend plugin registry.
+typedef llvm::Registry<FrontendAction> FrontendPluginRegistry;
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h
new file mode 100644
index 000000000000..2edc7e1f4ab4
--- /dev/null
+++ b/include/clang/Frontend/HeaderSearchOptions.h
@@ -0,0 +1,87 @@
+//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H
+#define LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H
+
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+
+namespace frontend {
+ /// IncludeDirGroup - Identifiers the group a include entry belongs to, which
+ /// represents its relative positive in the search list.
+ enum IncludeDirGroup {
+ Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`.
+ Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`)
+ System, ///< Like Angled, but marks system directories.
+ After ///< Like System, but searched after the system directories.
+ };
+}
+
+/// HeaderSearchOptions - Helper class for storing options related to the
+/// initialization of the HeaderSearch object.
+class HeaderSearchOptions {
+public:
+ struct Entry {
+ std::string Path;
+ frontend::IncludeDirGroup Group;
+ unsigned IsUserSupplied : 1;
+ unsigned IsFramework : 1;
+
+ Entry(llvm::StringRef _Path, frontend::IncludeDirGroup _Group,
+ bool _IsUserSupplied, bool _IsFramework)
+ : Path(_Path), Group(_Group), IsUserSupplied(_IsUserSupplied),
+ IsFramework(_IsFramework) {}
+ };
+
+ /// If non-empty, the directory to use as a "virtual system root" for include
+ /// paths.
+ std::string Sysroot;
+
+ /// User specified include entries.
+ std::vector<Entry> UserEntries;
+
+ /// A (system-path) delimited list of include paths to be added from the
+ /// environment following the user specified includes (but prior to builtin
+ /// and standard includes). This is parsed in the same manner as the CPATH
+ /// environment variable for gcc.
+ std::string EnvIncPath;
+
+ /// Per-language environmental include paths, see \see EnvIncPath.
+ std::string CEnvIncPath;
+ std::string ObjCEnvIncPath;
+ std::string CXXEnvIncPath;
+ std::string ObjCXXEnvIncPath;
+
+ /// If non-empty, the path to the compiler builtin include directory, which
+ /// will be searched following the user and environment includes.
+ std::string BuiltinIncludePath;
+
+ /// Include the system standard include search directories.
+ unsigned UseStandardIncludes : 1;
+
+ /// Whether header search information should be output as for -v.
+ unsigned Verbose : 1;
+
+public:
+ HeaderSearchOptions(llvm::StringRef _Sysroot = "")
+ : Sysroot(_Sysroot), UseStandardIncludes(true) {}
+
+ /// AddPath - Add the \arg Path path to the specified \arg Group list.
+ void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group,
+ bool IsUserSupplied, bool IsFramework) {
+ UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework));
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index cc8b3a03e3e8..85861fab4a22 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -29,6 +29,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/System/DataTypes.h"
#include <deque>
@@ -78,7 +79,7 @@ public:
/// \brief Receives the target triple.
///
/// \returns true to indicate the target triple is invalid or false otherwise.
- virtual bool ReadTargetTriple(const std::string &Triple) {
+ virtual bool ReadTargetTriple(llvm::StringRef Triple) {
return false;
}
@@ -87,18 +88,18 @@ public:
/// \param PCHPredef The start of the predefines buffer in the PCH
/// file.
///
- /// \param PCHPredefLen The length of the predefines buffer in the PCH
- /// file.
- ///
/// \param PCHBufferID The FileID for the PCH predefines buffer.
///
+ /// \param OriginalFileName The original file name for the PCH, which will
+ /// appear as an entry in the predefines buffer.
+ ///
/// \param SuggestedPredefines If necessary, additional definitions are added
/// here.
///
/// \returns true to indicate the predefines are invalid or false otherwise.
- virtual bool ReadPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+ virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID,
+ llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
return false;
}
@@ -123,10 +124,10 @@ public:
: PP(PP), Reader(Reader), NumHeaderInfos(0) {}
virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
- virtual bool ReadTargetTriple(const std::string &Triple);
- virtual bool ReadPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+ virtual bool ReadTargetTriple(llvm::StringRef Triple);
+ virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID,
+ llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines);
virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI);
virtual void ReadCounter(unsigned Value);
@@ -312,10 +313,13 @@ private:
/// the PCH file.
llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls;
- /// \brief The original file name that was used to build the PCH
- /// file.
+ /// \brief The original file name that was used to build the PCH file, which
+ /// may have been modified for relocatable-pch support.
std::string OriginalFileName;
+ /// \brief The actual original file name that was used to build the PCH file.
+ std::string ActualOriginalFileName;
+
/// \brief Whether this precompiled header is a relocatable PCH file.
bool RelocatablePCH;
@@ -444,9 +448,7 @@ private:
void MaybeAddSystemRootToFilename(std::string &Filename);
PCHReadResult ReadPCHBlock();
- bool CheckPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
- FileID PCHBufferID);
+ bool CheckPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID);
bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record);
PCHReadResult ReadSourceManagerBlock();
PCHReadResult ReadSLocEntryRecord(unsigned ID);
@@ -625,13 +627,15 @@ public:
/// \brief Retrieve the IdentifierInfo for the named identifier.
///
- /// This routine builds a new IdentifierInfo for the given
- /// identifier. If any declarations with this name are visible from
- /// translation unit scope, their declarations will be deserialized
- /// and introduced into the declaration chain of the
- /// identifier. FIXME: if this identifier names a macro, deserialize
- /// the macro.
+ /// This routine builds a new IdentifierInfo for the given identifier. If any
+ /// declarations with this name are visible from translation unit scope, their
+ /// declarations will be deserialized and introduced into the declaration
+ /// chain of the identifier. FIXME: if this identifier names a macro,
+ /// deserialize the macro.
virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd);
+ IdentifierInfo* get(llvm::StringRef Name) {
+ return get(Name.begin(), Name.end());
+ }
/// \brief Load the contents of the global method pool for a given
/// selector.
diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h
index 22427eb67103..b520f4be1d31 100644
--- a/include/clang/Frontend/PCHWriter.h
+++ b/include/clang/Frontend/PCHWriter.h
@@ -52,7 +52,8 @@ struct UnsafeQualTypeDenseMapInfo {
return QualType::getFromOpaquePtr((void*) 2);
}
static inline unsigned getHashValue(QualType T) {
- assert(!T.getFastQualifiers() && "hash invalid for types with fast quals");
+ assert(!T.getLocalFastQualifiers() &&
+ "hash invalid for types with fast quals");
uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
}
diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h
new file mode 100644
index 000000000000..f0c1d3c2c38d
--- /dev/null
+++ b/include/clang/Frontend/PreprocessorOptions.h
@@ -0,0 +1,57 @@
+//===--- PreprocessorOptionms.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_
+#define LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_
+
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class Preprocessor;
+class LangOptions;
+
+/// PreprocessorOptions - This class is used for passing the various options
+/// used in preprocessor initialization to InitializePreprocessor().
+class PreprocessorOptions {
+public:
+ std::vector<std::pair<std::string, bool/*isUndef*/> > Macros;
+ std::vector<std::string> Includes;
+ std::vector<std::string> MacroIncludes;
+
+ unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler
+ /// and target specific predefines.
+
+ /// The implicit PCH included at the start of the translation unit, or empty.
+ std::string ImplicitPCHInclude;
+
+ /// The implicit PTH input included at the start of the translation unit, or
+ /// empty.
+ std::string ImplicitPTHInclude;
+
+ /// If given, a PTH cache file to use for speeding up header parsing.
+ std::string TokenCache;
+
+public:
+ PreprocessorOptions() : UsePredefines(true) {}
+
+ void addMacroDef(llvm::StringRef Name) {
+ Macros.push_back(std::make_pair(Name, false));
+ }
+ void addMacroUndef(llvm::StringRef Name) {
+ Macros.push_back(std::make_pair(Name, true));
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
new file mode 100644
index 000000000000..a712a3d1bb05
--- /dev/null
+++ b/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -0,0 +1,37 @@
+//===--- PreprocessorOutputOptions.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H
+#define LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H
+
+namespace clang {
+
+/// PreprocessorOutputOptions - Options for controlling the C preprocessor
+/// output (e.g., -E).
+class PreprocessorOutputOptions {
+public:
+ unsigned ShowCPP : 1; ///< Print normal preprocessed output.
+ unsigned ShowMacros : 1; ///< Print macro definitions.
+ unsigned ShowLineMarkers : 1; ///< Show #line markers.
+ unsigned ShowComments : 1; ///< Show comments.
+ unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
+
+public:
+ PreprocessorOutputOptions() {
+ ShowCPP = 1;
+ ShowMacros = 0;
+ ShowLineMarkers = 1;
+ ShowComments = 0;
+ ShowMacroComments = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
index 3c5c6267c632..d727e4800727 100644
--- a/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -34,12 +34,15 @@ class TextDiagnosticPrinter : public DiagnosticClient {
SourceLocation LastWarningLoc;
FullSourceLoc LastLoc;
- bool LastCaretDiagnosticWasNote;
+ unsigned LastCaretDiagnosticWasNote : 1;
+ unsigned OwnsOutputStream : 1;
public:
- TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags);
+ TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags,
+ bool OwnsOutputStream = false);
+ virtual ~TextDiagnosticPrinter();
- void BeginSourceFile(const LangOptions &LO) {
+ void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) {
LangOpts = &LO;
}
diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def
index 6aca15a75427..35f5debe5cf0 100644
--- a/include/clang/Frontend/TypeXML.def
+++ b/include/clang/Frontend/TypeXML.def
@@ -65,9 +65,9 @@
NODE_XML(QualType, "CvQualifiedType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*'
- ATTRIBUTE_OPT_XML(isConstQualified(), "const") // boolean
- ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile") // boolean
- ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict") // boolean
+ ATTRIBUTE_OPT_XML(isLocalConstQualified(), "const") // boolean
+ ATTRIBUTE_OPT_XML(isLocalVolatileQualified(), "volatile") // boolean
+ ATTRIBUTE_OPT_XML(isLocalRestrictQualified(), "restrict") // boolean
ATTRIBUTE_OPT_XML(getObjCGCAttr(), "objc_gc") // Qualifiers::GC
ATTRIBUTE_OPT_XML(getAddressSpace(), "address_space") // unsigned
END_NODE_XML
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 3c670286545b..27c14c917015 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -1,4 +1,4 @@
-//===--- Utils.h - Misc utilities for the front-end------------------------===//
+//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,42 +14,57 @@
#ifndef LLVM_CLANG_FRONTEND_UTILS_H
#define LLVM_CLANG_FRONTEND_UTILS_H
+#include "llvm/ADT/StringRef.h"
#include <vector>
#include <string>
namespace llvm {
+class Triple;
class raw_ostream;
class raw_fd_ostream;
}
namespace clang {
-class Preprocessor;
-class MinimalAction;
-class TargetInfo;
-class Diagnostic;
class ASTConsumer;
+class Decl;
+class DependencyOutputOptions;
+class Diagnostic;
+class DiagnosticOptions;
+class HeaderSearch;
+class HeaderSearchOptions;
class IdentifierTable;
-class SourceManager;
class LangOptions;
-class Decl;
+class MinimalAction;
+class Preprocessor;
+class PreprocessorOptions;
+class PreprocessorOutputOptions;
+class SourceManager;
class Stmt;
+class TargetInfo;
+
+/// Normalize \arg File for use in a user defined #include directive (in the
+/// predefines buffer).
+std::string NormalizeDashIncludePath(llvm::StringRef File);
+
+/// Apply the header search options to get given HeaderSearch object.
+void ApplyHeaderSearchOptions(HeaderSearch &HS,
+ const HeaderSearchOptions &HSOpts,
+ const LangOptions &Lang,
+ const llvm::Triple &triple);
+
+/// InitializePreprocessor - Initialize the preprocessor getting it and the
+/// environment ready to process a single file.
+void InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorOptions &PPOpts,
+ const HeaderSearchOptions &HSOpts);
/// ProcessWarningOptions - Initialize the diagnostic client and process the
/// warning options specified on the command line.
-bool ProcessWarningOptions(Diagnostic &Diags,
- std::vector<std::string> &Warnings,
- bool Pedantic, bool PedanticErrors,
- bool NoWarnings);
-
-/// DoPrintPreprocessedInput - Implement -E -dM mode.
-void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream* OS);
+bool ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts);
/// DoPrintPreprocessedInput - Implement -E mode.
void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS,
- bool EnableCommentOutput,
- bool EnableMacroCommentOutput,
- bool DisableLineMarkers,
- bool DumpDefines);
+ const PreprocessorOutputOptions &Opts);
/// RewriteMacrosInInput - Implement -rewrite-macros mode.
void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS);
@@ -67,13 +82,12 @@ bool CheckDiagnostics(Preprocessor &PP);
/// AttachDependencyFileGen - Create a dependency file generator, and attach
/// it to the given preprocessor. This takes ownership of the output stream.
-void AttachDependencyFileGen(Preprocessor *PP, llvm::raw_ostream *OS,
- std::vector<std::string> &Targets,
- bool IncludeSystemHeaders, bool PhonyTarget);
+void AttachDependencyFileGen(Preprocessor &PP,
+ const DependencyOutputOptions &Opts);
/// CacheTokens - Cache tokens for use with PCH. Note that this requires
/// a seekable stream.
-void CacheTokens(Preprocessor& PP, llvm::raw_fd_ostream* OS);
+void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS);
} // end namespace clang
diff --git a/include/clang/Frontend/VerifyDiagnosticsClient.h b/include/clang/Frontend/VerifyDiagnosticsClient.h
new file mode 100644
index 000000000000..6f7ebbe537f9
--- /dev/null
+++ b/include/clang/Frontend/VerifyDiagnosticsClient.h
@@ -0,0 +1,82 @@
+//===-- VerifyDiagnosticsClient.h - Verifying Diagnostic Client -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
+#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+
+class Diagnostic;
+class SourceMgr;
+class TextDiagnosticBuffer;
+
+/// VerifyDiagnosticsClient - Create a diagnostic client which will use markers
+/// in the input source to check that all the emitted diagnostics match those
+/// expected.
+///
+/// USING THE DIAGNOSTIC CHECKER:
+///
+/// Indicating that a line expects an error or a warning is simple. Put a
+/// comment on the line that has the diagnostic, use "expected-{error,warning}"
+/// to tag if it's an expected error or warning, and place the expected text
+/// between {{ and }} markers. The full text doesn't have to be included, only
+/// enough to ensure that the correct diagnostic was emitted.
+///
+/// Here's an example:
+///
+/// int A = B; // expected-error {{use of undeclared identifier 'B'}}
+///
+/// You can place as many diagnostics on one line as you wish. To make the code
+/// more readable, you can use slash-newline to separate out the diagnostics.
+///
+/// The simple syntax above allows each specification to match exactly one
+/// error. You can use the extended syntax to customize this. The extended
+/// syntax is "expected-<type> <n> {{diag text}}", where <type> is one of
+/// "error", "warning" or "note", and <n> is a positive integer. This allows the
+/// diagnostic to appear as many times as specified. Example:
+///
+/// void f(); // expected-note 2 {{previous declaration is here}}
+///
+class VerifyDiagnosticsClient : public DiagnosticClient {
+public:
+ Diagnostic &Diags;
+ llvm::OwningPtr<DiagnosticClient> PrimaryClient;
+ llvm::OwningPtr<TextDiagnosticBuffer> Buffer;
+ Preprocessor *CurrentPreprocessor;
+ unsigned NumErrors;
+
+private:
+ void CheckDiagnostics();
+
+public:
+ /// Create a new verifying diagnostic client, which will issue errors to \arg
+ /// PrimaryClient when a diagnostic does not match what is expected (as
+ /// indicated in the source file). The verifying diagnostic client takes
+ /// ownership of \arg PrimaryClient.
+ VerifyDiagnosticsClient(Diagnostic &Diags, DiagnosticClient *PrimaryClient);
+ ~VerifyDiagnosticsClient();
+
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP);
+
+ virtual void EndSourceFile();
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+
+ /// HadErrors - Check if there were any mismatches in expected diagnostics.
+ bool HadErrors();
+};
+
+} // end namspace clang
+
+#endif
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
index ff1a17259e8a..ac5594e55d7d 100644
--- a/include/clang/Lex/PTHManager.h
+++ b/include/clang/Lex/PTHManager.h
@@ -119,8 +119,7 @@ public:
/// Create - This method creates PTHManager objects. The 'file' argument
/// is the name of the PTH file. This method returns NULL upon failure.
- static PTHManager *Create(const std::string& file, Diagnostic* Diags = 0,
- Diagnostic::Level failureLevel=Diagnostic::Warning);
+ static PTHManager *Create(const std::string& file, Diagnostic &Diags);
void setPreprocessor(Preprocessor *pp) { PP = pp; }
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 2783716b89ff..1c0036e3edcb 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -51,7 +51,7 @@ class DirectoryLookup;
class Preprocessor {
Diagnostic *Diags;
LangOptions Features;
- TargetInfo &Target;
+ const TargetInfo &Target;
FileManager &FileMgr;
SourceManager &SourceMgr;
ScratchBuffer *ScratchBuf;
@@ -94,6 +94,9 @@ class Preprocessor {
bool DisableMacroExpansion : 1; // True if macro expansion is disabled.
bool InMacroArgs : 1; // True if parsing fn macro invocation args.
+ /// Whether the preprocessor owns the header search object.
+ bool OwnsHeaderSearch : 1;
+
/// Identifiers - This is mapping/lookup information for all identifiers in
/// the program, including program keywords.
mutable IdentifierTable Identifiers;
@@ -207,9 +210,11 @@ private: // Cached tokens state.
std::vector<CachedTokensTy::size_type> BacktrackPositions;
public:
- Preprocessor(Diagnostic &diags, const LangOptions &opts, TargetInfo &target,
+ Preprocessor(Diagnostic &diags, const LangOptions &opts,
+ const TargetInfo &target,
SourceManager &SM, HeaderSearch &Headers,
- IdentifierInfoLookup *IILookup = 0);
+ IdentifierInfoLookup *IILookup = 0,
+ bool OwnsHeaderSearch = false);
~Preprocessor();
@@ -217,7 +222,7 @@ public:
void setDiagnostics(Diagnostic &D) { Diags = &D; }
const LangOptions &getLangOptions() const { return Features; }
- TargetInfo &getTargetInfo() const { return Target; }
+ const TargetInfo &getTargetInfo() const { return Target; }
FileManager &getFileManager() const { return FileMgr; }
SourceManager &getSourceManager() const { return SourceMgr; }
HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
@@ -498,6 +503,15 @@ public:
/// UCNs, etc.
std::string getSpelling(const Token &Tok) const;
+ /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
+ /// token is the characters used to represent the token in the source file
+ /// after trigraph expansion and escaped-newline folding. In particular, this
+ /// wants to get the true, uncanonicalized, spelling of things like digraphs
+ /// UCNs, etc.
+ static std::string getSpelling(const Token &Tok,
+ const SourceManager &SourceMgr,
+ const LangOptions &Features);
+
/// getSpelling - This method is used to get the spelling of a token into a
/// preallocated buffer, instead of as an std::string. The caller is required
/// to allocate enough space for the token, which is guaranteed to be at least
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index 8d910959b9fa..604eae1027aa 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -248,69 +248,6 @@ struct PPConditionalInfo {
bool FoundElse;
};
-/// TemplateIdAnnotation - Information about a template-id annotation
-/// token, which contains the template declaration, template
-/// arguments, whether those template arguments were types or
-/// expressions, and the source locations for important tokens. All of
-/// the information about template arguments is allocated directly
-/// after this structure.
-struct TemplateIdAnnotation {
- /// TemplateNameLoc - The location of the template name within the
- /// source.
- SourceLocation TemplateNameLoc;
-
- /// FIXME: Temporarily stores the name of a specialization
- IdentifierInfo *Name;
-
- /// FIXME: Temporarily stores the overloaded operator kind.
- OverloadedOperatorKind Operator;
-
- /// The declaration of the template corresponding to the
- /// template-name. This is an Action::DeclTy*.
- void *Template;
-
- /// The kind of template that Template refers to.
- TemplateNameKind Kind;
-
- /// The location of the '<' before the template argument
- /// list.
- SourceLocation LAngleLoc;
-
- /// The location of the '>' after the template argument
- /// list.
- SourceLocation RAngleLoc;
-
- /// NumArgs - The number of template arguments.
- unsigned NumArgs;
-
- /// \brief Retrieves a pointer to the template arguments
- void **getTemplateArgs() { return (void **)(this + 1); }
-
- /// \brief Retrieves a pointer to the array of template argument
- /// locations.
- SourceLocation *getTemplateArgLocations() {
- return (SourceLocation *)(getTemplateArgs() + NumArgs);
- }
-
- /// \brief Retrieves a pointer to the array of flags that states
- /// whether the template arguments are types.
- bool *getTemplateArgIsType() {
- return (bool *)(getTemplateArgLocations() + NumArgs);
- }
-
- static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
- TemplateIdAnnotation *TemplateId
- = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
- sizeof(void*) * NumArgs +
- sizeof(SourceLocation) * NumArgs +
- sizeof(bool) * NumArgs);
- TemplateId->NumArgs = NumArgs;
- return TemplateId;
- }
-
- void Destroy() { free(this); }
-};
-
} // end namespace clang
#endif
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 657a14fff082..a9b32133234a 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -1203,6 +1203,8 @@ public:
/// 'typename' keyword. FIXME: This will eventually be split into a
/// separate action.
///
+ /// \param TypenameLoc the location of the 'typename' keyword, if present
+ ///
/// \returns a representation of the using declaration.
virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
@@ -1210,7 +1212,8 @@ public:
const CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName);
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
/// ActOnParamDefaultArgument - Parse default argument for function parameter
virtual void ActOnParamDefaultArgument(DeclPtrTy param,
@@ -1577,7 +1580,7 @@ public:
/// parameter.
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
SourceLocation EqualLoc,
- ExprArg Default) {
+ const ParsedTemplateArgument &Default) {
}
/// ActOnTemplateParameterList - Called when a complete template
@@ -1632,7 +1635,6 @@ public:
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc) {
return TypeResult();
};
@@ -1737,7 +1739,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
@@ -1817,7 +1818,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr) {
return DeclResult();
@@ -2105,6 +2105,7 @@ public:
virtual DeclPtrTy ActOnForwardClassDeclaration(
SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
unsigned NumElts) {
return DeclPtrTy();
}
@@ -2329,6 +2330,47 @@ public:
///
/// \param S the scope in which the operator keyword occurs.
virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { }
+
+ /// \brief Code completion for an ObjC message expression that refers to
+ /// a class method.
+ ///
+ /// This code completion action is invoked when the code-completion token is
+ /// found after the class name.
+ ///
+ /// \param S the scope in which the message expression occurs.
+ /// \param FName the factory name.
+ /// \param FNameLoc the source location of the factory name.
+ virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
+ SourceLocation FNameLoc){ }
+
+ /// \brief Code completion for an ObjC message expression that refers to
+ /// an instance method.
+ ///
+ /// This code completion action is invoked when the code-completion token is
+ /// found after the receiver expression.
+ ///
+ /// \param S the scope in which the operator keyword occurs.
+ /// \param Receiver an expression for the receiver of the message.
+ virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { }
+
+ /// \brief Code completion for a list of protocol references in Objective-C,
+ /// such as P1 and P2 in \c id<P1,P2>.
+ ///
+ /// This code completion action is invoked prior to each identifier
+ /// in the protocol list.
+ ///
+ /// \param Protocols the set of protocols that have already been parsed.
+ ///
+ /// \param NumProtocols the number of protocols that have already been
+ /// parsed.
+ virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+ unsigned NumProtocols) { }
+
+ /// \brief Code completion for a protocol declaration or definition, after
+ /// the @protocol but before any identifier.
+ ///
+ /// \param S the scope in which the protocol declaration occurs.
+ virtual void CodeCompleteObjCProtocolDecl(Scope *S) { }
//@}
};
@@ -2398,6 +2440,7 @@ public:
virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
+ SourceLocation *SLocs,
unsigned NumElts);
virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc,
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h
index 9fcc845cb006..81bb3007baea 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Parse/AttributeList.h
@@ -57,6 +57,7 @@ public:
AT_analyzer_noreturn,
AT_annotate,
AT_blocks,
+ AT_cdecl,
AT_cleanup,
AT_const,
AT_constructor,
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index d539508e973b..7e7d0b3f28e8 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -25,7 +25,8 @@ namespace clang {
class IdentifierInfo;
class Preprocessor;
class Declarator;
-
+ struct TemplateIdAnnotation;
+
/// DeclSpec - This class captures information about "declaration specifiers",
/// which encompasses storage-class-specifiers, type-specifiers,
/// type-qualifiers, and function-specifiers.
@@ -642,13 +643,7 @@ public:
/// \param TemplateId the template-id annotation that describes the parsed
/// template-id. This UnqualifiedId instance will take ownership of the
/// \p TemplateId and will free it on destruction.
- void setTemplateId(TemplateIdAnnotation *TemplateId) {
- assert(TemplateId && "NULL template-id annotation?");
- Kind = IK_TemplateId;
- this->TemplateId = TemplateId;
- StartLocation = TemplateId->TemplateNameLoc;
- EndLocation = TemplateId->RAngleLoc;
- }
+ void setTemplateId(TemplateIdAnnotation *TemplateId);
/// \brief Return the source range that covers this unqualified-id.
SourceRange getSourceRange() const {
diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h
index 9bd69c5fdb68..5eb9635f06a1 100644
--- a/include/clang/Parse/Ownership.h
+++ b/include/clang/Parse/Ownership.h
@@ -654,41 +654,33 @@ namespace clang {
#endif
};
+ class ParsedTemplateArgument;
+
class ASTTemplateArgsPtr {
#if !defined(DISABLE_SMART_POINTERS)
ActionBase &Actions;
#endif
- void **Args;
- bool *ArgIsType;
+ ParsedTemplateArgument *Args;
mutable unsigned Count;
#if !defined(DISABLE_SMART_POINTERS)
- void destroy() {
- if (!Count)
- return;
-
- for (unsigned i = 0; i != Count; ++i)
- if (Args[i] && !ArgIsType[i])
- Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
-
- Count = 0;
- }
+ void destroy();
#endif
-
+
public:
- ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
+ ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args,
unsigned count) :
#if !defined(DISABLE_SMART_POINTERS)
Actions(actions),
#endif
- Args(args), ArgIsType(argIsType), Count(count) { }
+ Args(args), Count(count) { }
// FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
#if !defined(DISABLE_SMART_POINTERS)
Actions(Other.Actions),
#endif
- Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) {
+ Args(Other.Args), Count(Other.Count) {
#if !defined(DISABLE_SMART_POINTERS)
Other.Count = 0;
#endif
@@ -700,7 +692,6 @@ namespace clang {
Actions = Other.Actions;
#endif
Args = Other.Args;
- ArgIsType = Other.ArgIsType;
Count = Other.Count;
#if !defined(DISABLE_SMART_POINTERS)
Other.Count = 0;
@@ -712,22 +703,20 @@ namespace clang {
~ASTTemplateArgsPtr() { destroy(); }
#endif
- void **getArgs() const { return Args; }
- bool *getArgIsType() const {return ArgIsType; }
+ ParsedTemplateArgument *getArgs() const { return Args; }
unsigned size() const { return Count; }
- void reset(void **args, bool *argIsType, unsigned count) {
+ void reset(ParsedTemplateArgument *args, unsigned count) {
#if !defined(DISABLE_SMART_POINTERS)
destroy();
#endif
Args = args;
- ArgIsType = argIsType;
Count = count;
}
- void *operator[](unsigned Arg) const { return Args[Arg]; }
+ const ParsedTemplateArgument &operator[](unsigned Arg) const;
- void **release() const {
+ ParsedTemplateArgument *release() const {
#if !defined(DISABLE_SMART_POINTERS)
Count = 0;
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 1ca92edc9a8b..e7dabdbd5b66 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -114,7 +114,7 @@ public:
~Parser();
const LangOptions &getLang() const { return PP.getLangOptions(); }
- TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
+ const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
Preprocessor &getPreprocessor() const { return PP; }
Action &getActions() const { return Actions; }
@@ -179,6 +179,8 @@ public:
/// the EOF was encountered.
bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
+ DeclGroupPtrTy RetrievePendingObjCImpDecl();
+
private:
//===--------------------------------------------------------------------===//
// Low-Level token peeking and consumption methods.
@@ -331,7 +333,7 @@ private:
/// either "commit the consumed tokens" or revert to the previously marked
/// token position. Example:
///
- /// TentativeParsingAction TPA;
+ /// TentativeParsingAction TPA(*this);
/// ConsumeToken();
/// ....
/// TPA.Revert();
@@ -783,6 +785,7 @@ private:
AttributeList *prefixAttrs = 0);
DeclPtrTy ObjCImpDecl;
+ llvm::SmallVector<DeclPtrTy, 4> PendingObjCImpDecl;
DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
DeclPtrTy ParseObjCAtEndDeclaration(SourceLocation atLoc);
@@ -1226,13 +1229,18 @@ private:
Parser &P;
CXXScopeSpec &SS;
bool EnteredScope;
+ bool CreatedScope;
public:
DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss)
- : P(p), SS(ss), EnteredScope(false) {}
+ : P(p), SS(ss), EnteredScope(false), CreatedScope(false) {}
void EnterDeclaratorScope() {
assert(!EnteredScope && "Already entered the scope!");
assert(SS.isSet() && "C++ scope was not set!");
+
+ CreatedScope = true;
+ P.EnterScope(0); // Not a decl scope.
+
if (P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
SS.setScopeRep(0);
@@ -1245,6 +1253,8 @@ private:
assert(SS.isSet() && "C++ scope was cleared ?");
P.Actions.ActOnCXXExitDeclaratorScope(P.CurScope, SS);
}
+ if (CreatedScope)
+ P.ExitScope();
}
};
@@ -1347,9 +1357,7 @@ private:
DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
// C++ 14.3: Template arguments [temp.arg]
- typedef llvm::SmallVector<void *, 16> TemplateArgList;
- typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList;
- typedef llvm::SmallVector<SourceLocation, 16> TemplateArgLocationList;
+ typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
SourceLocation TemplateNameLoc,
@@ -1357,8 +1365,6 @@ private:
bool ConsumeLastToken,
SourceLocation &LAngleLoc,
TemplateArgList &TemplateArgs,
- TemplateArgIsTypeList &TemplateArgIsType,
- TemplateArgLocationList &TemplateArgLocations,
SourceLocation &RAngleLoc);
bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
@@ -1367,10 +1373,9 @@ private:
SourceLocation TemplateKWLoc = SourceLocation(),
bool AllowTypeAnnotation = true);
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
- bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
- TemplateArgIsTypeList &TemplateArgIsType,
- TemplateArgLocationList &TemplateArgLocations);
- void *ParseTemplateArgument(bool &ArgIsType);
+ bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+ ParsedTemplateArgument ParseTemplateTemplateArgument();
+ ParsedTemplateArgument ParseTemplateArgument();
DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd);
diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h
index 480b94f73f62..c6a1e53472c1 100644
--- a/include/clang/Parse/Scope.h
+++ b/include/clang/Parse/Scope.h
@@ -275,7 +275,8 @@ public:
AnyParent = Parent;
Depth = AnyParent ? AnyParent->Depth+1 : 0;
Flags = ScopeFlags;
-
+ WithinElse = false;
+
if (AnyParent) {
FnParent = AnyParent->FnParent;
BreakParent = AnyParent->BreakParent;
@@ -283,13 +284,10 @@ public:
ControlParent = AnyParent->ControlParent;
BlockParent = AnyParent->BlockParent;
TemplateParamParent = AnyParent->TemplateParamParent;
- WithinElse = AnyParent->WithinElse;
-
} else {
FnParent = BreakParent = ContinueParent = BlockParent = 0;
ControlParent = 0;
TemplateParamParent = 0;
- WithinElse = false;
}
// If this scope is a function or contains breaks/continues, remember it.
diff --git a/include/clang/Parse/Template.h b/include/clang/Parse/Template.h
new file mode 100644
index 000000000000..1f8ccfbf05c6
--- /dev/null
+++ b/include/clang/Parse/Template.h
@@ -0,0 +1,183 @@
+//===--- Template.h - Template Parsing Data Types -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides data structures that store the parsed representation of
+// templates.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_PARSE_TEMPLATE_H
+#define LLVM_CLANG_PARSE_TEMPLATE_H
+
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Ownership.h"
+#include <cassert>
+
+namespace clang {
+ /// \brief Represents the parsed form of a C++ template argument.
+ class ParsedTemplateArgument {
+ public:
+ /// \brief Describes the kind of template argument that was parsed.
+ enum KindType {
+ /// \brief A template type parameter, stored as a type.
+ Type,
+ /// \brief A non-type template parameter, stored as an expression.
+ NonType,
+ /// \brief A template template argument, stored as a template name.
+ Template
+ };
+
+ /// \brief Build an empty template argument. This template argument
+ ParsedTemplateArgument() : Kind(Type), Arg(0) { }
+
+ /// \brief Create a template type argument or non-type template argument.
+ ///
+ /// \param Arg the template type argument or non-type template argument.
+ /// \param Loc the location of the type.
+ ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
+ : Kind(Kind), Arg(Arg), Loc(Loc) { }
+
+ /// \brief Create a template template argument.
+ ///
+ /// \param SS the C++ scope specifier that precedes the template name, if
+ /// any.
+ ///
+ /// \param Template the template to which this template template
+ /// argument refers.
+ ///
+ /// \param TemplateLoc the location of the template name.
+ ParsedTemplateArgument(const CXXScopeSpec &SS,
+ ActionBase::TemplateTy Template,
+ SourceLocation TemplateLoc)
+ : Kind(ParsedTemplateArgument::Template), Arg(Template.get()),
+ Loc(TemplateLoc), SS(SS) { }
+
+ /// \brief Determine whether the given template argument is invalid.
+ bool isInvalid() { return Arg == 0; }
+
+ /// \brief Determine what kind of template argument we have.
+ KindType getKind() const { return Kind; }
+
+ /// \brief Retrieve the template type argument's type.
+ ActionBase::TypeTy *getAsType() const {
+ assert(Kind == Type && "Not a template type argument");
+ return Arg;
+ }
+
+ /// \brief Retrieve the non-type template argument's expression.
+ ActionBase::ExprTy *getAsExpr() const {
+ assert(Kind == NonType && "Not a non-type template argument");
+ return Arg;
+ }
+
+ /// \brief Retrieve the template template argument's template name.
+ ActionBase::TemplateTy getAsTemplate() const {
+ assert(Kind == Template && "Not a template template argument");
+ return ActionBase::TemplateTy::make(Arg);
+ }
+
+ /// \brief Retrieve the location of the template argument.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Retrieve the nested-name-specifier that precedes the template
+ /// name in a template template argument.
+ const CXXScopeSpec &getScopeSpec() const {
+ assert(Kind == Template &&
+ "Only template template arguments can have a scope specifier");
+ return SS;
+ }
+
+ private:
+ KindType Kind;
+
+ /// \brief The actual template argument representation, which may be
+ /// an \c ActionBase::TypeTy* (for a type), an ActionBase::ExprTy* (for an
+ /// expression), or an ActionBase::TemplateTy (for a template).
+ void *Arg;
+
+ /// \brief the location of the template argument.
+ SourceLocation Loc;
+
+ /// \brief The nested-name-specifier that can accompany a template template
+ /// argument.
+ CXXScopeSpec SS;
+ };
+
+ /// \brief Information about a template-id annotation
+ /// token.
+ ///
+ /// A template-id annotation token contains the template declaration,
+ /// template arguments, whether those template arguments were types,
+ /// expressions, or template names, and the source locations for important
+ /// tokens. All of the information about template arguments is allocated
+ /// directly after this structure.
+ struct TemplateIdAnnotation {
+ /// TemplateNameLoc - The location of the template name within the
+ /// source.
+ SourceLocation TemplateNameLoc;
+
+ /// FIXME: Temporarily stores the name of a specialization
+ IdentifierInfo *Name;
+
+ /// FIXME: Temporarily stores the overloaded operator kind.
+ OverloadedOperatorKind Operator;
+
+ /// The declaration of the template corresponding to the
+ /// template-name. This is an Action::TemplateTy.
+ void *Template;
+
+ /// The kind of template that Template refers to.
+ TemplateNameKind Kind;
+
+ /// The location of the '<' before the template argument
+ /// list.
+ SourceLocation LAngleLoc;
+
+ /// The location of the '>' after the template argument
+ /// list.
+ SourceLocation RAngleLoc;
+
+ /// NumArgs - The number of template arguments.
+ unsigned NumArgs;
+
+ /// \brief Retrieves a pointer to the template arguments
+ ParsedTemplateArgument *getTemplateArgs() {
+ return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
+ }
+
+ static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
+ TemplateIdAnnotation *TemplateId
+ = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
+ sizeof(ParsedTemplateArgument) * NumArgs);
+ TemplateId->NumArgs = NumArgs;
+ return TemplateId;
+ }
+
+ void Destroy() { free(this); }
+ };
+
+#if !defined(DISABLE_SMART_POINTERS)
+ inline void ASTTemplateArgsPtr::destroy() {
+ if (!Count)
+ return;
+
+ for (unsigned I = 0; I != Count; ++I)
+ if (Args[I].getKind() == ParsedTemplateArgument::NonType)
+ Actions.DeleteExpr(Args[I].getAsExpr());
+
+ Count = 0;
+ }
+#endif
+
+ inline const ParsedTemplateArgument &
+ ASTTemplateArgsPtr::operator[](unsigned Arg) const {
+ return Args[Arg];
+ }
+}
+
+#endif
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 5b3522c9eb49..43ff6869184d 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include <memory>
#include <string>
@@ -43,6 +44,10 @@ public:
/// \brief The different kinds of "chunks" that can occur within a code
/// completion string.
enum ChunkKind {
+ /// \brief The piece of text that the user is expected to type to
+ /// match the code-completion string, typically a keyword or the name of a
+ /// declarator or macro.
+ CK_TypedText,
/// \brief A piece of text that should be placed in the buffer, e.g.,
/// parentheses or a comma in a function call.
CK_Text,
@@ -55,7 +60,29 @@ public:
CK_Placeholder,
/// \brief A piece of text that describes something about the result but
/// should not be inserted into the buffer.
- CK_Informative
+ CK_Informative,
+ /// \brief A piece of text that describes the parameter that corresponds
+ /// to the code-completion location within a function call, message send,
+ /// macro invocation, etc.
+ CK_CurrentParameter,
+ /// \brief A left parenthesis ('(').
+ CK_LeftParen,
+ /// \brief A right parenthesis (')').
+ CK_RightParen,
+ /// \brief A left bracket ('[').
+ CK_LeftBracket,
+ /// \brief A right bracket (']').
+ CK_RightBracket,
+ /// \brief A left brace ('{').
+ CK_LeftBrace,
+ /// \brief A right brace ('}').
+ CK_RightBrace,
+ /// \brief A left angle bracket ('<').
+ CK_LeftAngle,
+ /// \brief A right angle bracket ('>').
+ CK_RightAngle,
+ /// \brief A comma separator (',').
+ CK_Comma
};
/// \brief One piece of the code completion string.
@@ -66,7 +93,7 @@ public:
union {
/// \brief The text string associated with a CK_Text, CK_Placeholder,
- /// or CK_Informative chunk.
+ /// CK_Informative, or CK_Comma chunk.
/// The string is owned by the chunk and will be deallocated
/// (with delete[]) when the chunk is destroyed.
const char *Text;
@@ -79,21 +106,22 @@ public:
Chunk() : Kind(CK_Text), Text(0) { }
- private:
- Chunk(ChunkKind Kind, const char *Text);
-
- public:
+ Chunk(ChunkKind Kind, llvm::StringRef Text = "");
+
/// \brief Create a new text chunk.
- static Chunk CreateText(const char *Text);
+ static Chunk CreateText(llvm::StringRef Text);
/// \brief Create a new optional chunk.
static Chunk CreateOptional(std::auto_ptr<CodeCompletionString> Optional);
/// \brief Create a new placeholder chunk.
- static Chunk CreatePlaceholder(const char *Placeholder);
+ static Chunk CreatePlaceholder(llvm::StringRef Placeholder);
/// \brief Create a new informative chunk.
- static Chunk CreateInformative(const char *Informative);
+ static Chunk CreateInformative(llvm::StringRef Informative);
+
+ /// \brief Create a new current-parameter chunk.
+ static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter);
/// \brief Destroy this chunk, deallocating any memory it owns.
void Destroy();
@@ -113,10 +141,28 @@ public:
typedef llvm::SmallVector<Chunk, 4>::const_iterator iterator;
iterator begin() const { return Chunks.begin(); }
iterator end() const { return Chunks.end(); }
+ bool empty() const { return Chunks.empty(); }
+ unsigned size() const { return Chunks.size(); }
+
+ Chunk &operator[](unsigned I) {
+ assert(I < size() && "Chunk index out-of-range");
+ return Chunks[I];
+ }
+
+ const Chunk &operator[](unsigned I) const {
+ assert(I < size() && "Chunk index out-of-range");
+ return Chunks[I];
+ }
+
+ /// \brief Add a new typed-text chunk.
+ /// The text string will be copied.
+ void AddTypedTextChunk(llvm::StringRef Text) {
+ Chunks.push_back(Chunk(CK_TypedText, Text));
+ }
/// \brief Add a new text chunk.
/// The text string will be copied.
- void AddTextChunk(const char *Text) {
+ void AddTextChunk(llvm::StringRef Text) {
Chunks.push_back(Chunk::CreateText(Text));
}
@@ -127,24 +173,46 @@ public:
/// \brief Add a new placeholder chunk.
/// The placeholder text will be copied.
- void AddPlaceholderChunk(const char *Placeholder) {
+ void AddPlaceholderChunk(llvm::StringRef Placeholder) {
Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
}
/// \brief Add a new informative chunk.
/// The text will be copied.
- void AddInformativeChunk(const char *Text) {
+ void AddInformativeChunk(llvm::StringRef Text) {
Chunks.push_back(Chunk::CreateInformative(Text));
}
+
+ /// \brief Add a new current-parameter chunk.
+ /// The text will be copied.
+ void AddCurrentParameterChunk(llvm::StringRef CurrentParameter) {
+ Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
+ }
+
+ /// \brief Add a new chunk.
+ void AddChunk(Chunk C) { Chunks.push_back(C); }
/// \brief Retrieve a string representation of the code completion string,
/// which is mainly useful for debugging.
- std::string getAsString() const;
+ std::string getAsString() const;
+
+ /// \brief Serialize this code-completion string to the given stream.
+ void Serialize(llvm::raw_ostream &OS) const;
+
+ /// \brief Deserialize a code-completion string from the given string.
+ static CodeCompletionString *Deserialize(llvm::StringRef &Str);
};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const CodeCompletionString &CCS);
+
/// \brief Abstract interface for a consumer of code-completion
/// information.
class CodeCompleteConsumer {
+protected:
+ /// \brief Whether to include macros in the code-completion results.
+ bool IncludeMacros;
+
public:
/// \brief Captures a result of code completion.
struct Result {
@@ -291,23 +359,32 @@ public:
Sema &S) const;
};
+ CodeCompleteConsumer() : IncludeMacros(false) { }
+
+ explicit CodeCompleteConsumer(bool IncludeMacros)
+ : IncludeMacros(IncludeMacros) { }
+
+ /// \brief Whether the code-completion consumer wants to see macros.
+ bool includeMacros() const { return IncludeMacros; }
+
/// \brief Deregisters and destroys this code-completion consumer.
virtual ~CodeCompleteConsumer();
/// \name Code-completion callbacks
//@{
/// \brief Process the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
unsigned NumResults) { }
-
- /// \brief Process the set of overload candidates.
+
+ /// \param S the semantic-analyzer object for which code-completion is being
+ /// done.
///
/// \param CurrentArg the index of the current argument.
///
/// \param Candidates an array of overload candidates.
///
/// \param NumCandidates the number of overload candidates
- virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates) { }
//@}
@@ -316,24 +393,43 @@ public:
/// \brief A simple code-completion consumer that prints the results it
/// receives in a simple format.
class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
- /// \brief The semantic-analysis object to which this code-completion
- /// consumer is attached.
- Sema &SemaRef;
-
/// \brief The raw output stream.
llvm::raw_ostream &OS;
public:
/// \brief Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
- PrintingCodeCompleteConsumer(Sema &S, llvm::raw_ostream &OS)
- : SemaRef(S), OS(OS) { }
+ PrintingCodeCompleteConsumer(bool IncludeMacros,
+ llvm::raw_ostream &OS)
+ : CodeCompleteConsumer(IncludeMacros), OS(OS) { }
+
+ /// \brief Prints the finalized code-completion results.
+ virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
+ unsigned NumResults);
+
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates);
+};
+
+/// \brief A code-completion consumer that prints the results it receives
+/// in a format that is parsable by the CIndex library.
+class CIndexCodeCompleteConsumer : public CodeCompleteConsumer {
+ /// \brief The raw output stream.
+ llvm::raw_ostream &OS;
+
+public:
+ /// \brief Create a new CIndex code-completion consumer that prints its
+ /// results to the given raw output stream in a format readable to the CIndex
+ /// library.
+ CIndexCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS)
+ : CodeCompleteConsumer(IncludeMacros), OS(OS) { }
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
unsigned NumResults);
- virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates);
};
diff --git a/include/clang/Sema/ParseAST.h b/include/clang/Sema/ParseAST.h
index 8a245d03cdaa..f6cff2a023e6 100644
--- a/include/clang/Sema/ParseAST.h
+++ b/include/clang/Sema/ParseAST.h
@@ -20,7 +20,7 @@ namespace clang {
class ASTContext;
class CodeCompleteConsumer;
class Sema;
-
+
/// \brief Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed.
///
@@ -30,11 +30,13 @@ namespace clang {
/// \param CompleteTranslationUnit When true, the parsed file is
/// considered to be a complete translation unit, and any
/// end-of-translation-unit wrapup will be performed.
+ ///
+ /// \param CompletionConsumer If given, an object to consume code completion
+ /// results.
void ParseAST(Preprocessor &pp, ASTConsumer *C,
ASTContext &Ctx, bool PrintStats = false,
bool CompleteTranslationUnit = true,
- CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data) = 0,
- void *CreateCodeCompleterData = 0);
+ CodeCompleteConsumer *CompletionConsumer = 0);
} // end namespace clang
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 8562249479ca..dc13e7f4688c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -35,7 +35,7 @@ enum FloatingRank {
};
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
- TargetInfo &t,
+ const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
bool FreeMem, unsigned size_reserve) :
@@ -256,9 +256,9 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
= new (*this) MemberSpecializationInfo(Tmpl, TSK);
}
-UnresolvedUsingDecl *
+NamedDecl *
ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
- llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>::iterator Pos
+ llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
= InstantiatedFromUnresolvedUsingDecl.find(UUD);
if (Pos == InstantiatedFromUnresolvedUsingDecl.end())
return 0;
@@ -268,7 +268,10 @@ ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
void
ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD,
- UnresolvedUsingDecl *UUD) {
+ NamedDecl *UUD) {
+ assert((isa<UnresolvedUsingValueDecl>(UUD) ||
+ isa<UnresolvedUsingTypenameDecl>(UUD)) &&
+ "original declaration is not an unresolved using decl");
assert(!InstantiatedFromUnresolvedUsingDecl[UD] &&
"Already noted what using decl what instantiated from");
InstantiatedFromUnresolvedUsingDecl[UD] = UUD;
@@ -1186,7 +1189,7 @@ QualType ASTContext::getNoReturnType(QualType T) {
}
}
- return getQualifiedType(ResultType, T.getQualifiers());
+ return getQualifiedType(ResultType, T.getLocalQualifiers());
}
/// getComplexType - Return the uniqued reference to the type for a complex
@@ -2350,6 +2353,12 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
return DTN->CanonicalTemplateName;
}
+bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) {
+ X = getCanonicalTemplateName(X);
+ Y = getCanonicalTemplateName(Y);
+ return X.getAsVoidPointer() == Y.getAsVoidPointer();
+}
+
TemplateArgument
ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
switch (Arg.getKind()) {
@@ -2357,12 +2366,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
return Arg;
case TemplateArgument::Expression:
- // FIXME: Build canonical expression?
return Arg;
case TemplateArgument::Declaration:
return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
+ case TemplateArgument::Template:
+ return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
+
case TemplateArgument::Integral:
return TemplateArgument(*Arg.getAsIntegral(),
getCanonicalType(Arg.getIntegralType()));
@@ -2427,7 +2438,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) {
const ArrayType *ASTContext::getAsArrayType(QualType T) {
// Handle the non-qualified case efficiently.
- if (!T.hasQualifiers()) {
+ if (!T.hasLocalQualifiers()) {
// Handle the common positive case fast.
if (const ArrayType *AT = dyn_cast<ArrayType>(T))
return AT;
@@ -2732,12 +2743,22 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) {
return 1;
}
+static RecordDecl *
+CreateRecordDecl(ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id) {
+ if (Ctx.getLangOptions().CPlusPlus)
+ return CXXRecordDecl::Create(Ctx, TK, DC, L, Id);
+ else
+ return RecordDecl::Create(Ctx, TK, DC, L, Id);
+}
+
// getCFConstantStringType - Return the type used for constant CFStrings.
QualType ASTContext::getCFConstantStringType() {
if (!CFConstantStringTypeDecl) {
CFConstantStringTypeDecl =
- RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get("NSConstantString"));
+ CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("NSConstantString"));
+
QualType FieldTypes[4];
// const int *isa;
@@ -2774,8 +2795,8 @@ void ASTContext::setCFConstantStringType(QualType T) {
QualType ASTContext::getObjCFastEnumerationStateType() {
if (!ObjCFastEnumerationStateTypeDecl) {
ObjCFastEnumerationStateTypeDecl =
- RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get("__objcFastEnumerationState"));
+ CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__objcFastEnumerationState"));
QualType FieldTypes[] = {
UnsignedLongTy,
@@ -2807,8 +2828,8 @@ QualType ASTContext::getBlockDescriptorType() {
RecordDecl *T;
// FIXME: Needs the FlagAppleBlock bit.
- T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get("__block_descriptor"));
+ T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__block_descriptor"));
QualType FieldTypes[] = {
UnsignedLongTy,
@@ -2850,8 +2871,8 @@ QualType ASTContext::getBlockDescriptorExtendedType() {
RecordDecl *T;
// FIXME: Needs the FlagAppleBlock bit.
- T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get("__block_descriptor_withcopydispose"));
+ T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__block_descriptor_withcopydispose"));
QualType FieldTypes[] = {
UnsignedLongTy,
@@ -2920,8 +2941,8 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
++UniqueBlockByRefTypeID << '_' << DeclName;
RecordDecl *T;
- T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get(Name.str()));
+ T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get(Name.str()));
T->startDefinition();
QualType Int32Ty = IntTy;
assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
@@ -2970,8 +2991,8 @@ QualType ASTContext::getBlockParmType(
llvm::raw_svector_ostream(Name) << "__block_literal_"
<< ++UniqueBlockParmTypeID;
RecordDecl *T;
- T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get(Name.str()));
+ T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get(Name.str()));
QualType FieldTypes[] = {
getPointerType(VoidPtrTy),
IntTy,
@@ -3053,6 +3074,54 @@ int ASTContext::getObjCEncodingTypeSize(QualType type) {
return sz / getTypeSize(CharTy);
}
+/// getObjCEncodingForBlockDecl - Return the encoded type for this method
+/// declaration.
+void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,
+ std::string& S) {
+ const BlockDecl *Decl = Expr->getBlockDecl();
+ QualType BlockTy =
+ Expr->getType()->getAs<BlockPointerType>()->getPointeeType();
+ // Encode result type.
+ getObjCEncodingForType(cast<FunctionType>(BlockTy)->getResultType(), S);
+ // Compute size of all parameters.
+ // Start with computing size of a pointer in number of bytes.
+ // FIXME: There might(should) be a better way of doing this computation!
+ SourceLocation Loc;
+ int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy);
+ int ParmOffset = PtrSize;
+ for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+ E = Decl->param_end(); PI != E; ++PI) {
+ QualType PType = (*PI)->getType();
+ int sz = getObjCEncodingTypeSize(PType);
+ assert (sz > 0 && "BlockExpr - Incomplete param type");
+ ParmOffset += sz;
+ }
+ // Size of the argument frame
+ S += llvm::utostr(ParmOffset);
+ // Block pointer and offset.
+ S += "@?0";
+ ParmOffset = PtrSize;
+
+ // Argument types.
+ ParmOffset = PtrSize;
+ for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E =
+ Decl->param_end(); PI != E; ++PI) {
+ ParmVarDecl *PVDecl = *PI;
+ QualType PType = PVDecl->getOriginalType();
+ if (const ArrayType *AT =
+ dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
+ // Use array's original type only if it has known number of
+ // elements.
+ if (!isa<ConstantArrayType>(AT))
+ PType = PVDecl->getType();
+ } else if (PType->isFunctionType())
+ PType = PVDecl->getType();
+ getObjCEncodingForType(PType, S);
+ S += llvm::utostr(ParmOffset);
+ ParmOffset += getObjCEncodingTypeSize(PType);
+ }
+}
+
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
@@ -4186,8 +4255,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
return LHS;
// If the qualifiers are different, the types aren't compatible... mostly.
- Qualifiers LQuals = LHSCan.getQualifiers();
- Qualifiers RQuals = RHSCan.getQualifiers();
+ Qualifiers LQuals = LHSCan.getLocalQualifiers();
+ Qualifiers RQuals = RHSCan.getLocalQualifiers();
if (LQuals != RQuals) {
// If any of these qualifiers are different, we have a type
// mismatch.
@@ -4394,7 +4463,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
//===----------------------------------------------------------------------===//
unsigned ASTContext::getIntWidth(QualType T) {
- if (T == BoolTy)
+ if (T->isBooleanType())
return 1;
if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
return FWIT->getWidth();
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index e541406790a6..0f0b22d65f6f 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -30,6 +30,7 @@ add_clang_library(clangAST
TemplateName.cpp
Type.cpp
TypeLoc.cpp
+ TypePrinter.cpp
)
add_dependencies(clangAST ClangDiagnosticAST)
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index b59b45f6467e..023bca436339 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -76,31 +76,31 @@ void CXXBasePaths::swap(CXXBasePaths &Other) {
std::swap(DetectedVirtual, Other.DetectedVirtual);
}
-bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) {
+bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) const {
CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
/*DetectVirtual=*/false);
return isDerivedFrom(Base, Paths);
}
-bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) {
+bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const {
if (getCanonicalDecl() == Base->getCanonicalDecl())
return false;
- Paths.setOrigin(this);
+ Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths);
}
bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
void *UserData,
- CXXBasePaths &Paths) {
+ CXXBasePaths &Paths) const {
bool FoundPath = false;
ASTContext &Context = getASTContext();
- for (base_class_iterator BaseSpec = bases_begin(), BaseSpecEnd = bases_end();
- BaseSpec != BaseSpecEnd; ++BaseSpec) {
+ for (base_class_const_iterator BaseSpec = bases_begin(),
+ BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) {
// Find the record of the base class subobjects for this type.
- QualType BaseType = Context.getCanonicalType(BaseSpec->getType());
- BaseType = BaseType.getUnqualifiedType();
+ QualType BaseType = Context.getCanonicalType(BaseSpec->getType())
+ .getUnqualifiedType();
// C++ [temp.dep]p3:
// In the definition of a class template or a member of a class template,
@@ -183,7 +183,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
return FoundPath;
}
-bool CXXRecordDecl::FindBaseClass(CXXBaseSpecifier *Specifier,
+bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *BaseRecord) {
assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
@@ -192,7 +192,7 @@ bool CXXRecordDecl::FindBaseClass(CXXBaseSpecifier *Specifier,
->getCanonicalDecl() == BaseRecord;
}
-bool CXXRecordDecl::FindTagMember(CXXBaseSpecifier *Specifier,
+bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
@@ -208,7 +208,7 @@ bool CXXRecordDecl::FindTagMember(CXXBaseSpecifier *Specifier,
return false;
}
-bool CXXRecordDecl::FindOrdinaryMember(CXXBaseSpecifier *Specifier,
+bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
@@ -225,9 +225,10 @@ bool CXXRecordDecl::FindOrdinaryMember(CXXBaseSpecifier *Specifier,
return false;
}
-bool CXXRecordDecl::FindNestedNameSpecifierMember(CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *Name) {
+bool CXXRecordDecl::
+FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index a6996a4bfe5c..bdc804722c41 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -289,6 +289,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD))
return true;
+ if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD))
+ return cast<UsingShadowDecl>(this)->getTargetDecl() ==
+ cast<UsingShadowDecl>(OldD)->getTargetDecl();
+
// For non-function declarations, if the declarations are of the
// same kind then this must be a redeclaration, or semantic analysis
// would not have given us the new declaration.
@@ -308,7 +312,7 @@ bool NamedDecl::hasLinkage() const {
NamedDecl *NamedDecl::getUnderlyingDecl() {
NamedDecl *ND = this;
while (true) {
- if (UsingDecl *UD = dyn_cast<UsingDecl>(ND))
+ if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
ND = UD->getTargetDecl();
else if (ObjCCompatibleAliasDecl *AD
= dyn_cast<ObjCCompatibleAliasDecl>(ND))
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 6cfdcdd3e50e..831f552489f9 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -97,7 +97,7 @@ bool Decl::isTemplateParameterPack() const {
}
bool Decl::isFunctionOrFunctionTemplate() const {
- if (const UsingDecl *UD = dyn_cast<UsingDecl>(this))
+ if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this))
return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
@@ -189,10 +189,11 @@ ASTContext &Decl::getASTContext() const {
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
switch (DeclKind) {
- default:
- if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
- return IDNS_Ordinary;
- assert(0 && "Unknown decl kind!");
+ case Function:
+ case CXXMethod:
+ case CXXConstructor:
+ case CXXDestructor:
+ case CXXConversion:
case OverloadedFunction:
case Typedef:
case EnumConstant:
@@ -200,8 +201,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ImplicitParam:
case ParmVar:
case NonTypeTemplateParm:
- case Using:
- case UnresolvedUsing:
case ObjCMethod:
case ObjCContainer:
case ObjCCategory:
@@ -210,6 +209,16 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCCompatibleAlias:
return IDNS_Ordinary;
+ case UsingShadow:
+ return 0; // we'll actually overwrite this later
+
+ case UnresolvedUsingValue:
+ case UnresolvedUsingTypename:
+ return IDNS_Ordinary | IDNS_Using;
+
+ case Using:
+ return IDNS_Using;
+
case ObjCProtocol:
return IDNS_ObjCProtocol;
@@ -256,6 +265,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ClassTemplatePartialSpecialization:
return 0;
}
+
+ return 0;
}
void Decl::addAttr(Attr *NewAttr) {
@@ -663,6 +674,13 @@ void DeclContext::buildLookup(DeclContext *DCtx) {
if (D->getDeclContext() == DCtx)
makeDeclVisibleInContextImpl(ND);
+ // Insert any forward-declared Objective-C interfaces into the lookup
+ // data structure.
+ if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D))
+ for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
+ I != IEnd; ++I)
+ makeDeclVisibleInContextImpl(I->getInterface());
+
// If this declaration is itself a transparent declaration context,
// add its members (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index b4c0c59733e5..a21c93ffcdc9 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -211,7 +211,7 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context,
if (!ArgType.isConstQualified())
AcceptsConst = false;
}
- if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
+ if (!Context.hasSameUnqualifiedType(ArgType, ClassType))
continue;
MD = Method;
// We have a single argument of type cv X or cv X&, i.e. we've found the
@@ -276,10 +276,13 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
const_cast<CXXRecordDecl*>(this)));
- if (ClassType != Context.getCanonicalType(ArgType))
+ if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
return;
// This is a copy assignment operator.
+ // Note on the decl that it is a copy assignment operator.
+ OpDecl->setCopyAssignment(true);
+
// Suppress the implicit declaration of a copy constructor.
UserDeclaredCopyAssignment = true;
@@ -749,6 +752,33 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
(getNumParams() > 1 && getParamDecl(1)->hasDefaultArg());
}
+bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const {
+ if ((getNumParams() < 1) ||
+ (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
+ (getPrimaryTemplate() == 0) ||
+ (getDescribedFunctionTemplate() != 0))
+ return false;
+
+ const ParmVarDecl *Param = getParamDecl(0);
+
+ ASTContext &Context = getASTContext();
+ CanQualType ParamType = Context.getCanonicalType(Param->getType());
+
+ // Strip off the lvalue reference, if any.
+ if (CanQual<LValueReferenceType> ParamRefType
+ = ParamType->getAs<LValueReferenceType>())
+ ParamType = ParamRefType->getPointeeType();
+
+
+ // Is it the same as our our class type?
+ CanQualType ClassTy
+ = Context.getCanonicalType(Context.getTagDeclType(getParent()));
+ if (ParamType.getUnqualifiedType() != ClassTy)
+ return false;
+
+ return true;
+}
+
CXXDestructorDecl *
CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
@@ -761,12 +791,6 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
}
void
-CXXDestructorDecl::Destroy(ASTContext& C) {
- C.Deallocate(BaseOrMemberDestructions);
- CXXMethodDecl::Destroy(C);
-}
-
-void
CXXConstructorDecl::Destroy(ASTContext& C) {
C.Deallocate(BaseOrMemberInitializers);
CXXMethodDecl::Destroy(C);
@@ -890,22 +914,36 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
}
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
- SourceLocation UL, NamedDecl* Target,
- NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) {
- return new (C) UsingDecl(DC, L, NNR, TargetNL, UL, Target,
- TargetNNS, IsTypeNameArg);
-}
-
-UnresolvedUsingDecl *UnresolvedUsingDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation UsingLoc,
- SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc,
- DeclarationName TargetName,
- bool IsTypeNameArg) {
- return new (C) UnresolvedUsingDecl(DC, UsingLoc, TargetNNR, TargetNNS,
- TargetNameLoc, TargetName, IsTypeNameArg);
+ SourceLocation L, SourceRange NNR, SourceLocation UL,
+ NestedNameSpecifier* TargetNNS, DeclarationName Name,
+ bool IsTypeNameArg) {
+ return new (C) UsingDecl(DC, L, NNR, UL, TargetNNS, Name, IsTypeNameArg);
+}
+
+UnresolvedUsingValueDecl *
+UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc,
+ DeclarationName TargetName) {
+ return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
+ TargetNNR, TargetNNS,
+ TargetNameLoc, TargetName);
+}
+
+UnresolvedUsingTypenameDecl *
+UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc,
+ DeclarationName TargetName) {
+ return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc,
+ TargetNNR, TargetNNS,
+ TargetNameLoc,
+ TargetName.getAsIdentifierInfo());
}
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 7b48b724c0eb..c33720f5633a 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -571,34 +571,55 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
//===----------------------------------------------------------------------===//
ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const *Elts, unsigned nElts,
+ ObjCInterfaceDecl *const *Elts,
+ const SourceLocation *Locs,
+ unsigned nElts,
ASTContext &C)
: Decl(ObjCClass, DC, L) {
- ForwardDecls.set(Elts, nElts, C);
+ setClassList(C, Elts, Locs, nElts);
}
+void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
+ const SourceLocation *Locs, unsigned Num) {
+ ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num,
+ llvm::alignof<ObjCClassRef>());
+ for (unsigned i = 0; i < Num; ++i)
+ new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]);
+
+ NumDecls = Num;
+}
ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ObjCInterfaceDecl *const *Elts,
+ const SourceLocation *Locs,
unsigned nElts) {
- return new (C) ObjCClassDecl(DC, L, Elts, nElts, C);
+ return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C);
}
void ObjCClassDecl::Destroy(ASTContext &C) {
-
- // FIXME: There is no clear ownership policy now for referenced
- // ObjCInterfaceDecls. Some of them can be forward declarations that
- // are never later defined (in which case the ObjCClassDecl owns them)
- // or the ObjCInterfaceDecl later becomes a real definition later. Ideally
- // we should have separate objects for forward declarations and definitions,
- // obviating this problem. Because of this situation, referenced
- // ObjCInterfaceDecls are destroyed in ~TranslationUnit.
-
- ForwardDecls.Destroy(C);
+ // ObjCInterfaceDecls registered with a DeclContext will get destroyed
+ // when the DeclContext is destroyed. For those created only by a forward
+ // declaration, the first @class that created the ObjCInterfaceDecl gets
+ // to destroy it.
+ // FIXME: Note that this ownership role is very brittle; a better
+ // polict is surely need in the future.
+ for (iterator I = begin(), E = end(); I !=E ; ++I) {
+ ObjCInterfaceDecl *ID = I->getInterface();
+ if (ID->isForwardDecl() && ID->getLocStart() == getLocStart())
+ ID->Destroy(C);
+ }
+
+ C.Deallocate(ForwardDecls);
Decl::Destroy(C);
}
+SourceRange ObjCClassDecl::getSourceRange() const {
+ // FIXME: We should include the semicolon
+ assert(NumDecls);
+ return SourceRange(getLocation(), ForwardDecls[NumDecls-1].getLocation());
+}
+
//===----------------------------------------------------------------------===//
// ObjCForwardProtocolDecl
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index d9d195016bf3..131de8b2e11b 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -71,8 +71,10 @@ namespace {
void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
- void VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
+ void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingShadowDecl(UsingShadowDecl *D);
};
}
@@ -401,37 +403,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
}
}
- else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(D)) {
- if (DDecl->getNumBaseOrMemberDestructions() > 0) {
- // List order of base/member destruction for visualization purposes.
- assert (D->isThisDeclarationADefinition() && "Destructor with dtor-list");
- Proto += "/* : ";
- for (CXXDestructorDecl::destr_const_iterator *B = DDecl->destr_begin(),
- *E = DDecl->destr_end();
- B != E; ++B) {
- uintptr_t BaseOrMember = (*B);
- if (B != DDecl->destr_begin())
- Proto += ", ";
-
- if (DDecl->isMemberToDestroy(BaseOrMember)) {
- FieldDecl *FD = DDecl->getMemberToDestroy(BaseOrMember);
- Proto += "~";
- Proto += FD->getNameAsString();
- }
- else // FIXME. skip dependent types for now.
- if (const RecordType *RT =
- DDecl->getAnyBaseClassToDestroy(BaseOrMember)
- ->getAs<RecordType>()) {
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(RT->getDecl());
- Proto += "~";
- Proto += BaseDecl->getNameAsString();
- }
- Proto += "()";
- }
- Proto += " */";
- }
- }
else
AFT->getResultType().getAsStringInternal(Proto, Policy);
} else {
@@ -654,7 +625,7 @@ void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) {
for (ObjCClassDecl::iterator I = D->begin(), E = D->end();
I != E; ++I) {
if (I != D->begin()) Out << ", ";
- Out << (*I)->getNameAsString();
+ Out << I->getInterface()->getNameAsString();
}
}
@@ -856,11 +827,22 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
Out << "using ";
D->getTargetNestedNameDecl()->print(Out, Policy);
- Out << D->getTargetDecl()->getNameAsString();
+ Out << D->getNameAsString();
+}
+
+void
+DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+ Out << "using typename ";
+ D->getTargetNestedNameSpecifier()->print(Out, Policy);
+ Out << D->getDeclName().getAsString();
}
-void DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
+void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
Out << "using ";
D->getTargetNestedNameSpecifier()->print(Out, Policy);
- Out << D->getTargetName().getAsString();
+ Out << D->getDeclName().getAsString();
+}
+
+void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ // ignore
}
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 9ebc91afe142..0c14714812f5 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -220,7 +220,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
TemplateArgs.push_back(TemplateArgument(E));
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
- TemplateArgs.push_back(TemplateArgument(TTP));
+ TemplateArgs.push_back(TemplateArgument(TemplateName(TTP)));
}
}
@@ -285,11 +285,6 @@ TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
}
-SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
- return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
- : SourceLocation();
-}
-
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 8664c508615f..1ff068c9862c 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -18,6 +18,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
+#include <cstdio>
using namespace clang;
namespace clang {
@@ -310,6 +311,10 @@ DeclarationName DeclarationName::getUsingDirectiveName() {
return DeclarationName(Ptr);
}
+void DeclarationName::dump() const {
+ fprintf(stderr, "%s\n", getAsString().c_str());
+}
+
DeclarationNameTable::DeclarationNameTable() {
CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index a8ea752a4a7e..90b50c61f989 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -490,6 +490,8 @@ const char *CastExpr::getCastKindName() const {
return "BitCast";
case CastExpr::CK_NoOp:
return "NoOp";
+ case CastExpr::CK_BaseToDerived:
+ return "BaseToDerived";
case CastExpr::CK_DerivedToBase:
return "DerivedToBase";
case CastExpr::CK_Dynamic:
@@ -812,6 +814,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
}
return false;
}
+
+ case CXXTemporaryObjectExprClass:
+ case CXXConstructExprClass:
+ return false;
+
case ObjCMessageExprClass:
return false;
@@ -853,15 +860,19 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
- case CXXFunctionalCastExprClass:
- // If this is a cast to void, check the operand. Otherwise, the result of
- // the cast is unused.
- if (getType()->isVoidType())
+ case CXXFunctionalCastExprClass: {
+ const CastExpr *CE = cast<CastExpr>(this);
+
+ // If this is a cast to void or a constructor conversion, check the operand.
+ // Otherwise, the result of the cast is unused.
+ if (CE->getCastKind() == CastExpr::CK_ToVoid ||
+ CE->getCastKind() == CastExpr::CK_ConstructorConversion)
return (cast<CastExpr>(this)->getSubExpr()
->isUnusedResultAWarning(Loc, R1, R2, Ctx));
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
+ }
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 7c6fc41ef12b..0ba4608ee198 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -323,6 +323,14 @@ Expr *CXXMemberCallExpr::getImplicitObjectArgument() {
return 0;
}
+SourceRange CXXMemberCallExpr::getSourceRange() const {
+ SourceLocation LocStart = getCallee()->getLocStart();
+ if (LocStart.isInvalid() && getNumArgs() > 0)
+ LocStart = getArg(0)->getLocStart();
+ return SourceRange(LocStart, getRParenLoc());
+}
+
+
//===----------------------------------------------------------------------===//
// Named casts
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 7862c57c2d47..2689859e8e4a 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -204,13 +204,6 @@ public:
bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
};
-bool HasSideEffects(const Expr* E, ASTContext &Ctx) {
- Expr::EvalResult Result;
- EvalInfo Info(Ctx, Result);
-
- return HasSideEffect(Info).Visit(const_cast<Expr*>(E));
-}
-
} // end anonymous namespace
//===----------------------------------------------------------------------===//
@@ -964,7 +957,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
}
- if (HasSideEffects(E->getArg(0), Info.Ctx)) {
+ if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2)
return Success(-1ULL, E);
return Success(0, E);
@@ -1495,7 +1488,7 @@ public:
// FIXME: Missing: __real__/__imag__, array subscript of vector,
// member of vector, ImplicitValueInitExpr,
- // conditional ?:, comma
+ // conditional ?:
};
} // end anonymous namespace
@@ -1584,6 +1577,18 @@ bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
}
bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ if (E->getOpcode() == BinaryOperator::Comma) {
+ if (!EvaluateFloat(E->getRHS(), Result, Info))
+ return false;
+
+ // If we can't evaluate the LHS, it might have side effects;
+ // conservatively mark it.
+ if (!E->getLHS()->isEvaluatable(Info.Ctx))
+ Info.EvalResult.HasSideEffects = true;
+
+ return true;
+ }
+
// FIXME: Diagnostics? I really don't understand how the warnings
// and errors are supposed to work.
APFloat RHS(0.0);
@@ -1947,6 +1952,12 @@ bool Expr::isEvaluatable(ASTContext &Ctx) const {
return Evaluate(Result, Ctx) && !Result.HasSideEffects;
}
+bool Expr::HasSideEffects(ASTContext &Ctx) const {
+ Expr::EvalResult Result;
+ EvalInfo Info(Ctx, Result);
+ return HasSideEffect(Info).Visit(const_cast<Expr*>(this));
+}
+
APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const {
EvalResult EvalResult;
bool Result = Evaluate(EvalResult, Ctx);
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index d969776aa0ee..e26c0bba4934 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -167,7 +167,7 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS,
InnerPolicy);
} else {
// Print the type normally
- T->getAsStringInternal(TypeStr, InnerPolicy);
+ TypeStr = QualType(T, 0).getAsString(InnerPolicy);
}
OS << TypeStr;
break;
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 021c53e9514f..b9cfcfec74f0 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -226,8 +226,7 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
if (RD == Class)
BaseOffset = getBaseOffset(Base);
else {
- const ASTRecordLayout &Layout
- = Ctx.getASTRecordLayout(RD);
+ const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
BaseOffset = Offset + Layout.getBaseClassOffset(Base);
}
}
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index cf71d6b986a2..93bf8755d580 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -115,6 +115,7 @@ namespace {
// Exprs
void VisitExpr(Expr *Node);
void VisitCastExpr(CastExpr *Node);
+ void VisitImplicitCastExpr(ImplicitCastExpr *Node);
void VisitDeclRefExpr(DeclRefExpr *Node);
void VisitPredefinedExpr(PredefinedExpr *Node);
void VisitCharacterLiteral(CharacterLiteral *Node);
@@ -301,6 +302,12 @@ void StmtDumper::VisitCastExpr(CastExpr *Node) {
fprintf(F, " <%s>", Node->getCastKindName());
}
+void StmtDumper::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
+ VisitCastExpr(Node);
+ if (Node->isLvalueCast())
+ fprintf(F, " lvalue");
+}
+
void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
DumpExpr(Node);
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 02e0c74bb63a..4458c2b9cd25 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -695,6 +695,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
VisitType(Arg.getAsType());
break;
+ case TemplateArgument::Template:
+ VisitTemplateName(Arg.getAsTemplate());
+ break;
+
case TemplateArgument::Declaration:
VisitDecl(Arg.getAsDecl());
break;
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 94e1ca1e06e7..ff02f9a31cb2 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -58,6 +58,11 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
break;
+ case Template:
+ ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
+ .getAsVoidPointer());
+ break;
+
case Integral:
getAsIntegral()->Profile(ID);
getIntegralType().Profile(ID);
@@ -82,10 +87,19 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
switch (Argument.getKind()) {
case TemplateArgument::Expression:
return getSourceExpression()->getSourceRange();
+
case TemplateArgument::Declaration:
return getSourceDeclExpression()->getSourceRange();
+
case TemplateArgument::Type:
return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange();
+
+ case TemplateArgument::Template:
+ if (getTemplateQualifierRange().isValid())
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateNameLoc());
+ return SourceRange(getTemplateNameLoc());
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 779f6808b6c1..297534eaf1fc 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -98,6 +98,44 @@ const Type *Type::getArrayElementTypeNoTypeQual() const {
->getElementType().getTypePtr();
}
+/// \brief Retrieve the unqualified variant of the given type, removing as
+/// little sugar as possible.
+///
+/// This routine looks through various kinds of sugar to find the
+/// least-desuraged type that is unqualified. For example, given:
+///
+/// \code
+/// typedef int Integer;
+/// typedef const Integer CInteger;
+/// typedef CInteger DifferenceType;
+/// \endcode
+///
+/// Executing \c getUnqualifiedTypeSlow() on the type \c DifferenceType will
+/// desugar until we hit the type \c Integer, which has no qualifiers on it.
+QualType QualType::getUnqualifiedTypeSlow() const {
+ QualType Cur = *this;
+ while (true) {
+ if (!Cur.hasQualifiers())
+ return Cur;
+
+ const Type *CurTy = Cur.getTypePtr();
+ switch (CurTy->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Type::Class: { \
+ const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ if (!Ty->isSugared()) \
+ return Cur.getLocalUnqualifiedType(); \
+ Cur = Ty->desugar(); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+
+ return Cur.getUnqualifiedType();
+}
+
/// getDesugaredType - Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
/// the type is already concrete, it returns it unmodified. This is similar
@@ -425,7 +463,7 @@ bool Type::isSignedIntegerType() const {
bool Type::isUnsignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
- BT->getKind() <= BuiltinType::ULongLong;
+ BT->getKind() <= BuiltinType::UInt128;
}
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
@@ -453,8 +491,7 @@ bool Type::isFloatingType() const {
bool Type::isRealFloatingType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
- return BT->getKind() >= BuiltinType::Float &&
- BT->getKind() <= BuiltinType::LongDouble;
+ return BT->isFloatingPoint();
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealFloatingType();
return false;
@@ -808,6 +845,9 @@ static bool isDependent(const TemplateArgument &Arg) {
case TemplateArgument::Type:
return Arg.getAsType()->isDependentType();
+ case TemplateArgument::Template:
+ return Arg.getAsTemplate().isDependent();
+
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
// Never dependent
@@ -907,539 +947,6 @@ QualType QualifierCollector::apply(const Type *T) const {
return Context->getQualifiedType(T, *this);
}
-
-//===----------------------------------------------------------------------===//
-// Type Printing
-//===----------------------------------------------------------------------===//
-
-void QualType::dump(const char *msg) const {
- std::string R = "identifier";
- LangOptions LO;
- getAsStringInternal(R, PrintingPolicy(LO));
- if (msg)
- fprintf(stderr, "%s: %s\n", msg, R.c_str());
- else
- fprintf(stderr, "%s\n", R.c_str());
-}
-void QualType::dump() const {
- dump("");
-}
-
-void Type::dump() const {
- std::string S = "identifier";
- LangOptions LO;
- getAsStringInternal(S, PrintingPolicy(LO));
- fprintf(stderr, "%s\n", S.c_str());
-}
-
-
-
-static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
- if (TypeQuals & Qualifiers::Const) {
- if (!S.empty()) S += ' ';
- S += "const";
- }
- if (TypeQuals & Qualifiers::Volatile) {
- if (!S.empty()) S += ' ';
- S += "volatile";
- }
- if (TypeQuals & Qualifiers::Restrict) {
- if (!S.empty()) S += ' ';
- S += "restrict";
- }
-}
-
-std::string Qualifiers::getAsString() const {
- LangOptions LO;
- return getAsString(PrintingPolicy(LO));
-}
-
-// Appends qualifiers to the given string, separated by spaces. Will
-// prefix a space if the string is non-empty. Will not append a final
-// space.
-void Qualifiers::getAsStringInternal(std::string &S,
- const PrintingPolicy&) const {
- AppendTypeQualList(S, getCVRQualifiers());
- if (unsigned AddressSpace = getAddressSpace()) {
- if (!S.empty()) S += ' ';
- S += "__attribute__((address_space(";
- S += llvm::utostr_32(AddressSpace);
- S += ")))";
- }
- if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
- if (!S.empty()) S += ' ';
- S += "__attribute__((objc_gc(";
- if (GCAttrType == Qualifiers::Weak)
- S += "weak";
- else
- S += "strong";
- S += ")))";
- }
-}
-
-std::string QualType::getAsString() const {
- std::string S;
- LangOptions LO;
- getAsStringInternal(S, PrintingPolicy(LO));
- return S;
-}
-
-void
-QualType::getAsStringInternal(std::string &S,
- const PrintingPolicy &Policy) const {
- if (isNull()) {
- S += "NULL TYPE";
- return;
- }
-
- if (Policy.SuppressSpecifiers && getTypePtr()->isSpecifierType())
- return;
-
- // Print qualifiers as appropriate.
- Qualifiers Quals = getQualifiers();
- if (!Quals.empty()) {
- std::string TQS;
- Quals.getAsStringInternal(TQS, Policy);
-
- if (!S.empty()) {
- TQS += ' ';
- TQS += S;
- }
- std::swap(S, TQS);
- }
-
- getTypePtr()->getAsStringInternal(S, Policy);
-}
-
-void BuiltinType::getAsStringInternal(std::string &S,
- const PrintingPolicy &Policy) const {
- if (S.empty()) {
- S = getName(Policy.LangOpts);
- } else {
- // Prefix the basic type, e.g. 'int X'.
- S = ' ' + S;
- S = getName(Policy.LangOpts) + S;
- }
-}
-
-void FixedWidthIntType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- // FIXME: Once we get bitwidth attribute, write as
- // "int __attribute__((bitwidth(x)))".
- std::string prefix = "__clang_fixedwidth";
- prefix += llvm::utostr_32(Width);
- prefix += (char)(Signed ? 'S' : 'U');
- if (S.empty()) {
- S = prefix;
- } else {
- // Prefix the basic type, e.g. 'int X'.
- S = prefix + S;
- }
-}
-
-
-void ComplexType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- ElementType->getAsStringInternal(S, Policy);
- S = "_Complex " + S;
-}
-
-void PointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S = '*' + S;
-
- // Handle things like 'int (*A)[4];' correctly.
- // FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(getPointeeType()))
- S = '(' + S + ')';
-
- getPointeeType().getAsStringInternal(S, Policy);
-}
-
-void BlockPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S = '^' + S;
- PointeeType.getAsStringInternal(S, Policy);
-}
-
-void LValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S = '&' + S;
-
- // Handle things like 'int (&A)[4];' correctly.
- // FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(getPointeeTypeAsWritten()))
- S = '(' + S + ')';
-
- getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
-}
-
-void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S = "&&" + S;
-
- // Handle things like 'int (&&A)[4];' correctly.
- // FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(getPointeeTypeAsWritten()))
- S = '(' + S + ')';
-
- getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
-}
-
-void MemberPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- std::string C;
- Class->getAsStringInternal(C, Policy);
- C += "::*";
- S = C + S;
-
- // Handle things like 'int (Cls::*A)[4];' correctly.
- // FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(getPointeeType()))
- S = '(' + S + ')';
-
- getPointeeType().getAsStringInternal(S, Policy);
-}
-
-void ConstantArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S += '[';
- S += llvm::utostr(getSize().getZExtValue());
- S += ']';
-
- getElementType().getAsStringInternal(S, Policy);
-}
-
-void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S += "[]";
-
- getElementType().getAsStringInternal(S, Policy);
-}
-
-void VariableArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S += '[';
-
- if (getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(S, getIndexTypeCVRQualifiers());
- S += ' ';
- }
-
- if (getSizeModifier() == Static)
- S += "static";
- else if (getSizeModifier() == Star)
- S += '*';
-
- if (getSizeExpr()) {
- std::string SStr;
- llvm::raw_string_ostream s(SStr);
- getSizeExpr()->printPretty(s, 0, Policy);
- S += s.str();
- }
- S += ']';
-
- getElementType().getAsStringInternal(S, Policy);
-}
-
-void DependentSizedArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S += '[';
-
- if (getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(S, getIndexTypeCVRQualifiers());
- S += ' ';
- }
-
- if (getSizeModifier() == Static)
- S += "static";
- else if (getSizeModifier() == Star)
- S += '*';
-
- if (getSizeExpr()) {
- std::string SStr;
- llvm::raw_string_ostream s(SStr);
- getSizeExpr()->printPretty(s, 0, Policy);
- S += s.str();
- }
- S += ']';
-
- getElementType().getAsStringInternal(S, Policy);
-}
-
-void DependentSizedExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- getElementType().getAsStringInternal(S, Policy);
-
- S += " __attribute__((ext_vector_type(";
- if (getSizeExpr()) {
- std::string SStr;
- llvm::raw_string_ostream s(SStr);
- getSizeExpr()->printPretty(s, 0, Policy);
- S += s.str();
- }
- S += ")))";
-}
-
-void VectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- // FIXME: We prefer to print the size directly here, but have no way
- // to get the size of the type.
- S += " __attribute__((__vector_size__(";
- S += llvm::utostr_32(NumElements); // convert back to bytes.
- S += " * sizeof(" + ElementType.getAsString() + "))))";
- ElementType.getAsStringInternal(S, Policy);
-}
-
-void ExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- S += " __attribute__((ext_vector_type(";
- S += llvm::utostr_32(NumElements);
- S += ")))";
- ElementType.getAsStringInternal(S, Policy);
-}
-
-void TypeOfExprType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
- InnerString = ' ' + InnerString;
- std::string Str;
- llvm::raw_string_ostream s(Str);
- getUnderlyingExpr()->printPretty(s, 0, Policy);
- InnerString = "typeof " + s.str() + InnerString;
-}
-
-void TypeOfType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
- InnerString = ' ' + InnerString;
- std::string Tmp;
- getUnderlyingType().getAsStringInternal(Tmp, Policy);
- InnerString = "typeof(" + Tmp + ")" + InnerString;
-}
-
-void DecltypeType::getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
- InnerString = ' ' + InnerString;
- std::string Str;
- llvm::raw_string_ostream s(Str);
- getUnderlyingExpr()->printPretty(s, 0, Policy);
- InnerString = "decltype(" + s.str() + ")" + InnerString;
-}
-
-void FunctionNoProtoType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- // If needed for precedence reasons, wrap the inner part in grouping parens.
- if (!S.empty())
- S = "(" + S + ")";
-
- S += "()";
- if (getNoReturnAttr())
- S += " __attribute__((noreturn))";
- getResultType().getAsStringInternal(S, Policy);
-}
-
-void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- // If needed for precedence reasons, wrap the inner part in grouping parens.
- if (!S.empty())
- S = "(" + S + ")";
-
- S += "(";
- std::string Tmp;
- PrintingPolicy ParamPolicy(Policy);
- ParamPolicy.SuppressSpecifiers = false;
- for (unsigned i = 0, e = getNumArgs(); i != e; ++i) {
- if (i) S += ", ";
- getArgType(i).getAsStringInternal(Tmp, ParamPolicy);
- S += Tmp;
- Tmp.clear();
- }
-
- if (isVariadic()) {
- if (getNumArgs())
- S += ", ";
- S += "...";
- } else if (getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
- // Do not emit int() if we have a proto, emit 'int(void)'.
- S += "void";
- }
-
- S += ")";
- if (getNoReturnAttr())
- S += " __attribute__((noreturn))";
- getResultType().getAsStringInternal(S, Policy);
-}
-
-
-void TypedefType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
- InnerString = getDecl()->getIdentifier()->getName().str() + InnerString;
-}
-
-void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'parmname X'.
- InnerString = ' ' + InnerString;
-
- if (!Name)
- InnerString = "type-parameter-" + llvm::utostr_32(Depth) + '-' +
- llvm::utostr_32(Index) + InnerString;
- else
- InnerString = Name->getName().str() + InnerString;
-}
-
-void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- getReplacementType().getAsStringInternal(InnerString, Policy);
-}
-
-static void PrintTemplateArgument(std::string &Buffer,
- const TemplateArgument &Arg,
- const PrintingPolicy &Policy) {
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- assert(false && "Null template argument");
- break;
-
- case TemplateArgument::Type:
- Arg.getAsType().getAsStringInternal(Buffer, Policy);
- break;
-
- case TemplateArgument::Declaration:
- Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
- break;
-
- case TemplateArgument::Integral:
- Buffer = Arg.getAsIntegral()->toString(10, true);
- break;
-
- case TemplateArgument::Expression: {
- llvm::raw_string_ostream s(Buffer);
- Arg.getAsExpr()->printPretty(s, 0, Policy);
- break;
- }
-
- case TemplateArgument::Pack:
- assert(0 && "FIXME: Implement!");
- break;
- }
-}
-
-std::string
-TemplateSpecializationType::PrintTemplateArgumentList(
- const TemplateArgument *Args,
- unsigned NumArgs,
- const PrintingPolicy &Policy) {
- std::string SpecString;
- SpecString += '<';
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- if (Arg)
- SpecString += ", ";
-
- // Print the argument into a string.
- std::string ArgString;
- PrintTemplateArgument(ArgString, Args[Arg], Policy);
-
- // If this is the first argument and its string representation
- // begins with the global scope specifier ('::foo'), add a space
- // to avoid printing the diagraph '<:'.
- if (!Arg && !ArgString.empty() && ArgString[0] == ':')
- SpecString += ' ';
-
- SpecString += ArgString;
- }
-
- // If the last character of our string is '>', add another space to
- // keep the two '>''s separate tokens. We don't *have* to do this in
- // C++0x, but it's still good hygiene.
- if (SpecString[SpecString.size() - 1] == '>')
- SpecString += ' ';
-
- SpecString += '>';
-
- return SpecString;
-}
-
-// Sadly, repeat all that with TemplateArgLoc.
-std::string TemplateSpecializationType::
-PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
- const PrintingPolicy &Policy) {
- std::string SpecString;
- SpecString += '<';
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- if (Arg)
- SpecString += ", ";
-
- // Print the argument into a string.
- std::string ArgString;
- PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
-
- // If this is the first argument and its string representation
- // begins with the global scope specifier ('::foo'), add a space
- // to avoid printing the diagraph '<:'.
- if (!Arg && !ArgString.empty() && ArgString[0] == ':')
- SpecString += ' ';
-
- SpecString += ArgString;
- }
-
- // If the last character of our string is '>', add another space to
- // keep the two '>''s separate tokens. We don't *have* to do this in
- // C++0x, but it's still good hygiene.
- if (SpecString[SpecString.size() - 1] == '>')
- SpecString += ' ';
-
- SpecString += '>';
-
- return SpecString;
-}
-
-void
-TemplateSpecializationType::
-getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- std::string SpecString;
-
- {
- llvm::raw_string_ostream OS(SpecString);
- Template.print(OS, Policy);
- }
-
- SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs(), Policy);
- if (InnerString.empty())
- InnerString.swap(SpecString);
- else
- InnerString = SpecString + ' ' + InnerString;
-}
-
-void QualifiedNameType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- std::string MyString;
-
- {
- llvm::raw_string_ostream OS(MyString);
- NNS->print(OS, Policy);
- }
-
- std::string TypeStr;
- PrintingPolicy InnerPolicy(Policy);
- InnerPolicy.SuppressTagKind = true;
- InnerPolicy.SuppressScope = true;
- NamedType.getAsStringInternal(TypeStr, InnerPolicy);
-
- MyString += TypeStr;
- if (InnerString.empty())
- InnerString.swap(MyString);
- else
- InnerString = MyString + ' ' + InnerString;
-}
-
-void TypenameType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- std::string MyString;
-
- {
- llvm::raw_string_ostream OS(MyString);
- OS << "typename ";
- NNS->print(OS, Policy);
-
- if (const IdentifierInfo *Ident = getIdentifier())
- OS << Ident->getName();
- else if (const TemplateSpecializationType *Spec = getTemplateId()) {
- Spec->getTemplateName().print(OS, Policy, true);
- OS << TemplateSpecializationType::PrintTemplateArgumentList(
- Spec->getArgs(),
- Spec->getNumArgs(),
- Policy);
- }
- }
-
- if (InnerString.empty())
- InnerString.swap(MyString);
- else
- InnerString = MyString + ' ' + InnerString;
-}
-
void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
const ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **protocols,
@@ -1455,134 +962,3 @@ void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
else
Profile(ID, getDecl(), 0, 0);
}
-
-void ObjCInterfaceType::getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
-
- std::string ObjCQIString = getDecl()->getNameAsString();
- if (getNumProtocols()) {
- ObjCQIString += '<';
- bool isFirst = true;
- for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
- if (isFirst)
- isFirst = false;
- else
- ObjCQIString += ',';
- ObjCQIString += (*I)->getNameAsString();
- }
- ObjCQIString += '>';
- }
- InnerString = ObjCQIString + InnerString;
-}
-
-void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const {
- std::string ObjCQIString;
-
- if (isObjCIdType() || isObjCQualifiedIdType())
- ObjCQIString = "id";
- else if (isObjCClassType() || isObjCQualifiedClassType())
- ObjCQIString = "Class";
- else
- ObjCQIString = getInterfaceDecl()->getNameAsString();
-
- if (!qual_empty()) {
- ObjCQIString += '<';
- for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
- ObjCQIString += (*I)->getNameAsString();
- if (I+1 != E)
- ObjCQIString += ',';
- }
- ObjCQIString += '>';
- }
-
- PointeeType.getQualifiers().getAsStringInternal(ObjCQIString, Policy);
-
- if (!isObjCIdType() && !isObjCQualifiedIdType())
- ObjCQIString += " *"; // Don't forget the implicit pointer.
- else if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
-
- InnerString = ObjCQIString + InnerString;
-}
-
-void ElaboratedType::getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const {
- std::string TypeStr;
- PrintingPolicy InnerPolicy(Policy);
- InnerPolicy.SuppressTagKind = true;
- UnderlyingType.getAsStringInternal(InnerString, InnerPolicy);
-
- InnerString = std::string(getNameForTagKind(getTagKind())) + ' ' + InnerString;
-}
-
-void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- if (Policy.SuppressTag)
- return;
-
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
-
- const char *Kind = Policy.SuppressTagKind? 0 : getDecl()->getKindName();
- const char *ID;
- if (const IdentifierInfo *II = getDecl()->getIdentifier())
- ID = II->getNameStart();
- else if (TypedefDecl *Typedef = getDecl()->getTypedefForAnonDecl()) {
- Kind = 0;
- assert(Typedef->getIdentifier() && "Typedef without identifier?");
- ID = Typedef->getIdentifier()->getNameStart();
- } else
- ID = "<anonymous>";
-
- // If this is a class template specialization, print the template
- // arguments.
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
- const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- std::string TemplateArgsStr
- = TemplateSpecializationType::PrintTemplateArgumentList(
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size(),
- Policy);
- InnerString = TemplateArgsStr + InnerString;
- }
-
- if (!Policy.SuppressScope) {
- // Compute the full nested-name-specifier for this type. In C,
- // this will always be empty.
- std::string ContextStr;
- for (DeclContext *DC = getDecl()->getDeclContext();
- !DC->isTranslationUnit(); DC = DC->getParent()) {
- std::string MyPart;
- if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
- if (NS->getIdentifier())
- MyPart = NS->getNameAsString();
- } else if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
- const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- std::string TemplateArgsStr
- = TemplateSpecializationType::PrintTemplateArgumentList(
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size(),
- Policy);
- MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr;
- } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
- if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
- MyPart = Typedef->getIdentifier()->getName();
- else if (Tag->getIdentifier())
- MyPart = Tag->getIdentifier()->getName();
- }
-
- if (!MyPart.empty())
- ContextStr = MyPart + "::" + ContextStr;
- }
-
- if (Kind)
- InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString;
- else
- InnerString = ContextStr + ID + InnerString;
- } else
- InnerString = ID + InnerString;
-}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
new file mode 100644
index 000000000000..a48233378286
--- /dev/null
+++ b/lib/AST/TypePrinter.cpp
@@ -0,0 +1,728 @@
+//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to print types from Clang's type system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+ class TypePrinter {
+ PrintingPolicy Policy;
+
+ public:
+ explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
+
+ void Print(QualType T, std::string &S);
+ void PrintTag(const TagType *T, std::string &S);
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) \
+ void Print##CLASS(const CLASS##Type *T, std::string &S);
+#include "clang/AST/TypeNodes.def"
+ };
+}
+
+static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
+ if (TypeQuals & Qualifiers::Const) {
+ if (!S.empty()) S += ' ';
+ S += "const";
+ }
+ if (TypeQuals & Qualifiers::Volatile) {
+ if (!S.empty()) S += ' ';
+ S += "volatile";
+ }
+ if (TypeQuals & Qualifiers::Restrict) {
+ if (!S.empty()) S += ' ';
+ S += "restrict";
+ }
+}
+
+void TypePrinter::Print(QualType T, std::string &S) {
+ if (T.isNull()) {
+ S += "NULL TYPE";
+ return;
+ }
+
+ if (Policy.SuppressSpecifiers && T->isSpecifierType())
+ return;
+
+ // Print qualifiers as appropriate.
+ Qualifiers Quals = T.getLocalQualifiers();
+ if (!Quals.empty()) {
+ std::string TQS;
+ Quals.getAsStringInternal(TQS, Policy);
+
+ if (!S.empty()) {
+ TQS += ' ';
+ TQS += S;
+ }
+ std::swap(S, TQS);
+ }
+
+ switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) case Type::CLASS: \
+ Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \
+ break;
+#include "clang/AST/TypeNodes.def"
+ }
+}
+
+void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
+ if (S.empty()) {
+ S = T->getName(Policy.LangOpts);
+ } else {
+ // Prefix the basic type, e.g. 'int X'.
+ S = ' ' + S;
+ S = T->getName(Policy.LangOpts) + S;
+ }
+}
+
+void TypePrinter::PrintFixedWidthInt(const FixedWidthIntType *T,
+ std::string &S) {
+ // FIXME: Once we get bitwidth attribute, write as
+ // "int __attribute__((bitwidth(x)))".
+ std::string prefix = "__clang_fixedwidth";
+ prefix += llvm::utostr_32(T->getWidth());
+ prefix += (char)(T->isSigned() ? 'S' : 'U');
+ if (S.empty()) {
+ S = prefix;
+ } else {
+ // Prefix the basic type, e.g. 'int X'.
+ S = prefix + S;
+ }
+}
+
+void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
+ Print(T->getElementType(), S);
+ S = "_Complex " + S;
+}
+
+void TypePrinter::PrintPointer(const PointerType *T, std::string &S) {
+ S = '*' + S;
+
+ // Handle things like 'int (*A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeType()))
+ S = '(' + S + ')';
+
+ Print(T->getPointeeType(), S);
+}
+
+void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) {
+ S = '^' + S;
+ Print(T->getPointeeType(), S);
+}
+
+void TypePrinter::PrintLValueReference(const LValueReferenceType *T,
+ std::string &S) {
+ S = '&' + S;
+
+ // Handle things like 'int (&A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ S = '(' + S + ')';
+
+ Print(T->getPointeeTypeAsWritten(), S);
+}
+
+void TypePrinter::PrintRValueReference(const RValueReferenceType *T,
+ std::string &S) {
+ S = "&&" + S;
+
+ // Handle things like 'int (&&A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ S = '(' + S + ')';
+
+ Print(T->getPointeeTypeAsWritten(), S);
+}
+
+void TypePrinter::PrintMemberPointer(const MemberPointerType *T,
+ std::string &S) {
+ std::string C;
+ Print(QualType(T->getClass(), 0), C);
+ C += "::*";
+ S = C + S;
+
+ // Handle things like 'int (Cls::*A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeType()))
+ S = '(' + S + ')';
+
+ Print(T->getPointeeType(), S);
+}
+
+void TypePrinter::PrintConstantArray(const ConstantArrayType *T,
+ std::string &S) {
+ S += '[';
+ S += llvm::utostr(T->getSize().getZExtValue());
+ S += ']';
+
+ Print(T->getElementType(), S);
+}
+
+void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T,
+ std::string &S) {
+ S += "[]";
+ Print(T->getElementType(), S);
+}
+
+void TypePrinter::PrintVariableArray(const VariableArrayType *T,
+ std::string &S) {
+ S += '[';
+
+ if (T->getIndexTypeQualifiers().hasQualifiers()) {
+ AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
+ S += ' ';
+ }
+
+ if (T->getSizeModifier() == VariableArrayType::Static)
+ S += "static";
+ else if (T->getSizeModifier() == VariableArrayType::Star)
+ S += '*';
+
+ if (T->getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ T->getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ']';
+
+ Print(T->getElementType(), S);
+}
+
+void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T,
+ std::string &S) {
+ S += '[';
+
+ if (T->getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ T->getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ']';
+
+ Print(T->getElementType(), S);
+}
+
+void TypePrinter::PrintDependentSizedExtVector(
+ const DependentSizedExtVectorType *T,
+ std::string &S) {
+ Print(T->getElementType(), S);
+
+ S += " __attribute__((ext_vector_type(";
+ if (T->getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ T->getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ")))";
+}
+
+void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
+ // FIXME: We prefer to print the size directly here, but have no way
+ // to get the size of the type.
+ S += " __attribute__((__vector_size__(";
+ S += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
+ std::string ET;
+ Print(T->getElementType(), ET);
+ S += " * sizeof(" + ET + "))))";
+ Print(T->getElementType(), S);
+}
+
+void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
+ S += " __attribute__((ext_vector_type(";
+ S += llvm::utostr_32(T->getNumElements());
+ S += ")))";
+ Print(T->getElementType(), S);
+}
+
+void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
+ std::string &S) {
+ // If needed for precedence reasons, wrap the inner part in grouping parens.
+ if (!S.empty())
+ S = "(" + S + ")";
+
+ S += "(";
+ std::string Tmp;
+ PrintingPolicy ParamPolicy(Policy);
+ ParamPolicy.SuppressSpecifiers = false;
+ for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
+ if (i) S += ", ";
+ Print(T->getArgType(i), Tmp);
+ S += Tmp;
+ Tmp.clear();
+ }
+
+ if (T->isVariadic()) {
+ if (T->getNumArgs())
+ S += ", ";
+ S += "...";
+ } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
+ // Do not emit int() if we have a proto, emit 'int(void)'.
+ S += "void";
+ }
+
+ S += ")";
+ if (T->getNoReturnAttr())
+ S += " __attribute__((noreturn))";
+ Print(T->getResultType(), S);
+
+}
+
+void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
+ std::string &S) {
+ // If needed for precedence reasons, wrap the inner part in grouping parens.
+ if (!S.empty())
+ S = "(" + S + ")";
+
+ S += "()";
+ if (T->getNoReturnAttr())
+ S += " __attribute__((noreturn))";
+ Print(T->getResultType(), S);
+}
+
+void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ S = ' ' + S;
+ S = T->getDecl()->getIdentifier()->getName().str() + S;
+}
+
+void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
+ S = ' ' + S;
+ std::string Str;
+ llvm::raw_string_ostream s(Str);
+ T->getUnderlyingExpr()->printPretty(s, 0, Policy);
+ S = "typeof " + s.str() + S;
+}
+
+void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
+ S = ' ' + S;
+ std::string Tmp;
+ Print(T->getUnderlyingType(), Tmp);
+ S = "typeof(" + Tmp + ")" + S;
+}
+
+void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
+ S = ' ' + S;
+ std::string Str;
+ llvm::raw_string_ostream s(Str);
+ T->getUnderlyingExpr()->printPretty(s, 0, Policy);
+ S = "decltype(" + s.str() + ")" + S;
+}
+
+void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) {
+ if (Policy.SuppressTag)
+ return;
+
+ if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ InnerString = ' ' + InnerString;
+
+ const char *Kind = Policy.SuppressTagKind? 0 : T->getDecl()->getKindName();
+ const char *ID;
+ if (const IdentifierInfo *II = T->getDecl()->getIdentifier())
+ ID = II->getNameStart();
+ else if (TypedefDecl *Typedef = T->getDecl()->getTypedefForAnonDecl()) {
+ Kind = 0;
+ assert(Typedef->getIdentifier() && "Typedef without identifier?");
+ ID = Typedef->getIdentifier()->getNameStart();
+ } else
+ ID = "<anonymous>";
+
+ // If this is a class template specialization, print the template
+ // arguments.
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size(),
+ Policy);
+ InnerString = TemplateArgsStr + InnerString;
+ }
+
+ if (!Policy.SuppressScope) {
+ // Compute the full nested-name-specifier for this type. In C,
+ // this will always be empty.
+ std::string ContextStr;
+ for (DeclContext *DC = T->getDecl()->getDeclContext();
+ !DC->isTranslationUnit(); DC = DC->getParent()) {
+ std::string MyPart;
+ if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
+ if (NS->getIdentifier())
+ MyPart = NS->getNameAsString();
+ } else if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size(),
+ Policy);
+ MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr;
+ } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+ if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
+ MyPart = Typedef->getIdentifier()->getName();
+ else if (Tag->getIdentifier())
+ MyPart = Tag->getIdentifier()->getName();
+ }
+
+ if (!MyPart.empty())
+ ContextStr = MyPart + "::" + ContextStr;
+ }
+
+ if (Kind)
+ InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString;
+ else
+ InnerString = ContextStr + ID + InnerString;
+ } else
+ InnerString = ID + InnerString;
+}
+
+void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
+ PrintTag(T, S);
+}
+
+void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
+ PrintTag(T, S);
+}
+
+void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
+ std::string TypeStr;
+ PrintingPolicy InnerPolicy(Policy);
+ InnerPolicy.SuppressTagKind = true;
+ TypePrinter(InnerPolicy).Print(T->getUnderlyingType(), S);
+
+ S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S;
+}
+
+void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
+ std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
+ S = ' ' + S;
+
+ if (!T->getName())
+ S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
+ llvm::utostr_32(T->getIndex()) + S;
+ else
+ S = T->getName()->getName().str() + S;
+}
+
+void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
+ std::string &S) {
+ Print(T->getReplacementType(), S);
+}
+
+void TypePrinter::PrintTemplateSpecialization(
+ const TemplateSpecializationType *T,
+ std::string &S) {
+ std::string SpecString;
+
+ {
+ llvm::raw_string_ostream OS(SpecString);
+ T->getTemplateName().print(OS, Policy);
+ }
+
+ SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
+ T->getArgs(),
+ T->getNumArgs(),
+ Policy);
+ if (S.empty())
+ S.swap(SpecString);
+ else
+ S = SpecString + ' ' + S;
+}
+
+void TypePrinter::PrintQualifiedName(const QualifiedNameType *T,
+ std::string &S) {
+ std::string MyString;
+
+ {
+ llvm::raw_string_ostream OS(MyString);
+ T->getQualifier()->print(OS, Policy);
+ }
+
+ std::string TypeStr;
+ PrintingPolicy InnerPolicy(Policy);
+ InnerPolicy.SuppressTagKind = true;
+ InnerPolicy.SuppressScope = true;
+ TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
+
+ MyString += TypeStr;
+ if (S.empty())
+ S.swap(MyString);
+ else
+ S = MyString + ' ' + S;
+}
+
+void TypePrinter::PrintTypename(const TypenameType *T, std::string &S) {
+ std::string MyString;
+
+ {
+ llvm::raw_string_ostream OS(MyString);
+ OS << "typename ";
+ T->getQualifier()->print(OS, Policy);
+
+ if (const IdentifierInfo *Ident = T->getIdentifier())
+ OS << Ident->getName();
+ else if (const TemplateSpecializationType *Spec = T->getTemplateId()) {
+ Spec->getTemplateName().print(OS, Policy, true);
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Spec->getArgs(),
+ Spec->getNumArgs(),
+ Policy);
+ }
+ }
+
+ if (S.empty())
+ S.swap(MyString);
+ else
+ S = MyString + ' ' + S;
+}
+
+void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
+ std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ S = ' ' + S;
+
+ std::string ObjCQIString = T->getDecl()->getNameAsString();
+ if (T->getNumProtocols()) {
+ ObjCQIString += '<';
+ bool isFirst = true;
+ for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
+ E = T->qual_end();
+ I != E; ++I) {
+ if (isFirst)
+ isFirst = false;
+ else
+ ObjCQIString += ',';
+ ObjCQIString += (*I)->getNameAsString();
+ }
+ ObjCQIString += '>';
+ }
+ S = ObjCQIString + S;
+}
+
+void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
+ std::string &S) {
+ std::string ObjCQIString;
+
+ if (T->isObjCIdType() || T->isObjCQualifiedIdType())
+ ObjCQIString = "id";
+ else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
+ ObjCQIString = "Class";
+ else
+ ObjCQIString = T->getInterfaceDecl()->getNameAsString();
+
+ if (!T->qual_empty()) {
+ ObjCQIString += '<';
+ for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
+ E = T->qual_end();
+ I != E; ++I) {
+ ObjCQIString += (*I)->getNameAsString();
+ if (I+1 != E)
+ ObjCQIString += ',';
+ }
+ ObjCQIString += '>';
+ }
+
+ T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
+ Policy);
+
+ if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
+ ObjCQIString += " *"; // Don't forget the implicit pointer.
+ else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ S = ' ' + S;
+
+ S = ObjCQIString + S;
+}
+
+static void PrintTemplateArgument(std::string &Buffer,
+ const TemplateArgument &Arg,
+ const PrintingPolicy &Policy) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Null template argument");
+ break;
+
+ case TemplateArgument::Type:
+ Arg.getAsType().getAsStringInternal(Buffer, Policy);
+ break;
+
+ case TemplateArgument::Declaration:
+ Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
+ break;
+
+ case TemplateArgument::Template: {
+ llvm::raw_string_ostream s(Buffer);
+ Arg.getAsTemplate().print(s, Policy);
+ break;
+ }
+
+ case TemplateArgument::Integral:
+ Buffer = Arg.getAsIntegral()->toString(10, true);
+ break;
+
+ case TemplateArgument::Expression: {
+ llvm::raw_string_ostream s(Buffer);
+ Arg.getAsExpr()->printPretty(s, 0, Policy);
+ break;
+ }
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
+ }
+}
+
+std::string
+TemplateSpecializationType::PrintTemplateArgumentList(
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy) {
+ std::string SpecString;
+ SpecString += '<';
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (Arg)
+ SpecString += ", ";
+
+ // Print the argument into a string.
+ std::string ArgString;
+ PrintTemplateArgument(ArgString, Args[Arg], Policy);
+
+ // If this is the first argument and its string representation
+ // begins with the global scope specifier ('::foo'), add a space
+ // to avoid printing the diagraph '<:'.
+ if (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ SpecString += ' ';
+
+ SpecString += ArgString;
+ }
+
+ // If the last character of our string is '>', add another space to
+ // keep the two '>''s separate tokens. We don't *have* to do this in
+ // C++0x, but it's still good hygiene.
+ if (SpecString[SpecString.size() - 1] == '>')
+ SpecString += ' ';
+
+ SpecString += '>';
+
+ return SpecString;
+}
+
+// Sadly, repeat all that with TemplateArgLoc.
+std::string TemplateSpecializationType::
+PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ const PrintingPolicy &Policy) {
+ std::string SpecString;
+ SpecString += '<';
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (Arg)
+ SpecString += ", ";
+
+ // Print the argument into a string.
+ std::string ArgString;
+ PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
+
+ // If this is the first argument and its string representation
+ // begins with the global scope specifier ('::foo'), add a space
+ // to avoid printing the diagraph '<:'.
+ if (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ SpecString += ' ';
+
+ SpecString += ArgString;
+ }
+
+ // If the last character of our string is '>', add another space to
+ // keep the two '>''s separate tokens. We don't *have* to do this in
+ // C++0x, but it's still good hygiene.
+ if (SpecString[SpecString.size() - 1] == '>')
+ SpecString += ' ';
+
+ SpecString += '>';
+
+ return SpecString;
+}
+
+void QualType::dump(const char *msg) const {
+ std::string R = "identifier";
+ LangOptions LO;
+ getAsStringInternal(R, PrintingPolicy(LO));
+ if (msg)
+ fprintf(stderr, "%s: %s\n", msg, R.c_str());
+ else
+ fprintf(stderr, "%s\n", R.c_str());
+}
+void QualType::dump() const {
+ dump("");
+}
+
+void Type::dump() const {
+ QualType(this, 0).dump();
+}
+
+std::string Qualifiers::getAsString() const {
+ LangOptions LO;
+ return getAsString(PrintingPolicy(LO));
+}
+
+// Appends qualifiers to the given string, separated by spaces. Will
+// prefix a space if the string is non-empty. Will not append a final
+// space.
+void Qualifiers::getAsStringInternal(std::string &S,
+ const PrintingPolicy&) const {
+ AppendTypeQualList(S, getCVRQualifiers());
+ if (unsigned AddressSpace = getAddressSpace()) {
+ if (!S.empty()) S += ' ';
+ S += "__attribute__((address_space(";
+ S += llvm::utostr_32(AddressSpace);
+ S += ")))";
+ }
+ if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
+ if (!S.empty()) S += ' ';
+ S += "__attribute__((objc_gc(";
+ if (GCAttrType == Qualifiers::Weak)
+ S += "weak";
+ else
+ S += "strong";
+ S += ")))";
+ }
+}
+
+std::string QualType::getAsString() const {
+ std::string S;
+ LangOptions LO;
+ getAsStringInternal(S, PrintingPolicy(LO));
+ return S;
+}
+
+void QualType::getAsStringInternal(std::string &S,
+ const PrintingPolicy &Policy) const {
+ TypePrinter Printer(Policy);
+ Printer.Print(*this, S);
+}
+
diff --git a/lib/Analysis/AnalysisManager.cpp b/lib/Analysis/AnalysisManager.cpp
deleted file mode 100644
index c2733faa683c..000000000000
--- a/lib/Analysis/AnalysisManager.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//== AnalysisManager.cpp - Path sensitive analysis data manager ----*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the AnalysisManager class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/PathSensitive/AnalysisManager.h"
-#include "clang/Basic/SourceManager.h"
-
-using namespace clang;
-
-void AnalysisManager::DisplayFunction(Decl *D) {
-
- if (DisplayedFunction)
- return;
-
- DisplayedFunction = true;
-
- // FIXME: Is getCodeDecl() always a named decl?
- if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
- const NamedDecl *ND = cast<NamedDecl>(D);
- SourceManager &SM = getASTContext().getSourceManager();
- (llvm::errs() << "ANALYZE: "
- << SM.getPresumedLoc(ND->getLocation()).getFilename()
- << ' ' << ND->getNameAsString() << '\n').flush();
- }
-}
-
diff --git a/lib/Analysis/ArrayBoundChecker.cpp b/lib/Analysis/ArrayBoundChecker.cpp
new file mode 100644
index 000000000000..549a22bec172
--- /dev/null
+++ b/lib/Analysis/ArrayBoundChecker.cpp
@@ -0,0 +1,86 @@
+//== ArrayBoundChecker.cpp ------------------------------*- 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 ArrayBoundChecker, which is a path-sensitive check
+// which looks for an out-of-bound array element access.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN ArrayBoundChecker :
+ public CheckerVisitor<ArrayBoundChecker> {
+ BuiltinBug *BT;
+public:
+ ArrayBoundChecker() : BT(0) {}
+ static void *getTag();
+ void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
+};
+}
+
+void clang::RegisterArrayBoundChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new ArrayBoundChecker());
+}
+
+void *ArrayBoundChecker::getTag() {
+ static int x = 0; return &x;
+}
+
+void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
+ // Check for out of bound array element access.
+ const MemRegion *R = l.getAsRegion();
+ if (!R)
+ return;
+
+ R = R->StripCasts();
+
+ const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+ if (!ER)
+ return;
+
+ // Get the index of the accessed element.
+ DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+
+ const GRState *state = C.getState();
+
+ // Get the size of the array.
+ DefinedOrUnknownSVal NumElements
+ = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
+
+ const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
+ const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
+ if (StOutBound && !StInBound) {
+ ExplodedNode *N = C.GenerateNode(S, StOutBound, true);
+
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Out-of-bound array access",
+ "Access out-of-bound array element (buffer overflow)");
+
+ // FIXME: It would be nice to eventually make this diagnostic more clear,
+ // e.g., by referencing the original declaration or by saying *why* this
+ // reference is outside the range.
+
+ // Generate a report for this bug.
+ RangedBugReport *report =
+ new RangedBugReport(*BT, BT->getDescription(), N);
+
+ report->addRange(S->getSourceRange());
+
+ C.EmitReport(report);
+ }
+}
diff --git a/lib/Analysis/AttrNonNullChecker.cpp b/lib/Analysis/AttrNonNullChecker.cpp
index 1cf5d0c4af2d..01e1a1fcf69b 100644
--- a/lib/Analysis/AttrNonNullChecker.cpp
+++ b/lib/Analysis/AttrNonNullChecker.cpp
@@ -12,14 +12,28 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "GRExprEngineInternalChecks.h"
using namespace clang;
-void *AttrNonNullChecker::getTag() {
- static int x = 0;
- return &x;
+namespace {
+class VISIBILITY_HIDDEN AttrNonNullChecker
+ : public CheckerVisitor<AttrNonNullChecker> {
+ BugType *BT;
+public:
+ AttrNonNullChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+} // end anonymous namespace
+
+void clang::RegisterAttrNonNullChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new AttrNonNullChecker());
}
void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
diff --git a/lib/Analysis/BadCallChecker.cpp b/lib/Analysis/BadCallChecker.cpp
index 33bb5158d2b9..7a7ea188ba59 100644
--- a/lib/Analysis/BadCallChecker.cpp
+++ b/lib/Analysis/BadCallChecker.cpp
@@ -12,14 +12,27 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "GRExprEngineInternalChecks.h"
using namespace clang;
-void *BadCallChecker::getTag() {
- static int x = 0;
- return &x;
+namespace {
+class VISIBILITY_HIDDEN BadCallChecker : public CheckerVisitor<BadCallChecker> {
+ BuiltinBug *BT;
+public:
+ BadCallChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+} // end anonymous namespace
+
+void clang::RegisterBadCallChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new BadCallChecker());
}
void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
@@ -29,11 +42,11 @@ void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
if (ExplodedNode *N = C.GenerateNode(CE, true)) {
if (!BT)
- BT = new BuiltinBug(0, "Invalid function call",
+ BT = new BuiltinBug("Invalid function call",
"Called function pointer is a null or undefined pointer value");
EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+ new EnhancedBugReport(*BT, BT->getDescription(), N);
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
bugreporter::GetCalleeExpr(N));
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index 4781d5ec243e..c2ecfa1f417f 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -384,7 +384,7 @@ bool AuditCFNumberCreate::Audit(ExplodedNode* N,GRStateManager&){
if (!LV)
return false;
- const TypedRegion* R = dyn_cast<TypedRegion>(LV->getBaseRegion());
+ const TypedRegion* R = dyn_cast<TypedRegion>(LV->StripCasts());
if (!R)
return false;
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 888af9bd57a4..800a76fb0aee 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -268,20 +268,6 @@ SValuator::CastResult BasicStoreManager::Retrieve(const GRState *state,
case loc::MemRegionKind: {
const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
- if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
- // Just support void**, void***, intptr_t*, intptr_t**, etc., for now.
- // This is needed to handle OSCompareAndSwapPtr() and friends.
- ASTContext &Ctx = StateMgr.getContext();
- QualType T = ER->getLocationType(Ctx);
-
- if (!isHigherOrderRawPtr(T, Ctx))
- return SValuator::CastResult(state, UnknownVal());
-
- // FIXME: Should check for element 0.
- // Otherwise, strip the element region.
- R = ER->getSuperRegion();
- }
-
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
return SValuator::CastResult(state, UnknownVal());
@@ -291,7 +277,8 @@ SValuator::CastResult BasicStoreManager::Retrieve(const GRState *state,
if (!Val)
break;
- return CastRetrievedVal(*Val, state, cast<TypedRegion>(R), T);
+ return SValuator::CastResult(state,
+ CastRetrievedVal(*Val, cast<TypedRegion>(R), T));
}
case loc::ConcreteIntKind:
@@ -624,7 +611,7 @@ const GRState *BasicStoreManager::InvalidateRegion(const GRState *state,
const Expr *E,
unsigned Count,
InvalidatedSymbols *IS) {
- R = R->getBaseRegion();
+ R = R->StripCasts();
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
return state;
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 03614e83398f..55e5f174cb9f 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -308,7 +308,234 @@ public:
}
};
+//===----------------------------------------------------------------------===//
+// Reference-counting logic (typestate + counts).
+//===----------------------------------------------------------------------===//
+class VISIBILITY_HIDDEN RefVal {
+public:
+ enum Kind {
+ Owned = 0, // Owning reference.
+ NotOwned, // Reference is not owned by still valid (not freed).
+ Released, // Object has been released.
+ ReturnedOwned, // Returned object passes ownership to caller.
+ ReturnedNotOwned, // Return object does not pass ownership to caller.
+ ERROR_START,
+ ErrorDeallocNotOwned, // -dealloc called on non-owned object.
+ ErrorDeallocGC, // Calling -dealloc with GC enabled.
+ ErrorUseAfterRelease, // Object used after released.
+ ErrorReleaseNotOwned, // Release of an object that was not owned.
+ ERROR_LEAK_START,
+ ErrorLeak, // A memory leak due to excessive reference counts.
+ ErrorLeakReturned, // A memory leak due to the returning method not having
+ // the correct naming conventions.
+ ErrorGCLeakReturned,
+ ErrorOverAutorelease,
+ ErrorReturnedNotOwned
+ };
+
+private:
+ Kind kind;
+ RetEffect::ObjKind okind;
+ unsigned Cnt;
+ unsigned ACnt;
+ QualType T;
+
+ RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
+ : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
+
+ RefVal(Kind k, unsigned cnt = 0)
+ : kind(k), okind(RetEffect::AnyObj), Cnt(cnt), ACnt(0) {}
+
+public:
+ Kind getKind() const { return kind; }
+
+ RetEffect::ObjKind getObjKind() const { return okind; }
+
+ unsigned getCount() const { return Cnt; }
+ unsigned getAutoreleaseCount() const { return ACnt; }
+ unsigned getCombinedCounts() const { return Cnt + ACnt; }
+ void clearCounts() { Cnt = 0; ACnt = 0; }
+ void setCount(unsigned i) { Cnt = i; }
+ void setAutoreleaseCount(unsigned i) { ACnt = i; }
+
+ QualType getType() const { return T; }
+
+ // Useful predicates.
+
+ static bool isError(Kind k) { return k >= ERROR_START; }
+
+ static bool isLeak(Kind k) { return k >= ERROR_LEAK_START; }
+
+ bool isOwned() const {
+ return getKind() == Owned;
+ }
+
+ bool isNotOwned() const {
+ return getKind() == NotOwned;
+ }
+
+ bool isReturnedOwned() const {
+ return getKind() == ReturnedOwned;
+ }
+
+ bool isReturnedNotOwned() const {
+ return getKind() == ReturnedNotOwned;
+ }
+
+ bool isNonLeakError() const {
+ Kind k = getKind();
+ return isError(k) && !isLeak(k);
+ }
+
+ static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
+ unsigned Count = 1) {
+ return RefVal(Owned, o, Count, 0, t);
+ }
+
+ static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
+ unsigned Count = 0) {
+ return RefVal(NotOwned, o, Count, 0, t);
+ }
+
+ // Comparison, profiling, and pretty-printing.
+
+ bool operator==(const RefVal& X) const {
+ return kind == X.kind && Cnt == X.Cnt && T == X.T && ACnt == X.ACnt;
+ }
+
+ RefVal operator-(size_t i) const {
+ return RefVal(getKind(), getObjKind(), getCount() - i,
+ getAutoreleaseCount(), getType());
+ }
+
+ RefVal operator+(size_t i) const {
+ return RefVal(getKind(), getObjKind(), getCount() + i,
+ getAutoreleaseCount(), getType());
+ }
+
+ RefVal operator^(Kind k) const {
+ return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
+ getType());
+ }
+
+ RefVal autorelease() const {
+ return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
+ getType());
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddInteger((unsigned) kind);
+ ID.AddInteger(Cnt);
+ ID.AddInteger(ACnt);
+ ID.Add(T);
+ }
+
+ void print(llvm::raw_ostream& Out) const;
+};
+
+void RefVal::print(llvm::raw_ostream& Out) const {
+ if (!T.isNull())
+ Out << "Tracked Type:" << T.getAsString() << '\n';
+
+ switch (getKind()) {
+ default: assert(false);
+ case Owned: {
+ Out << "Owned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case NotOwned: {
+ Out << "NotOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case ReturnedOwned: {
+ Out << "ReturnedOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case ReturnedNotOwned: {
+ Out << "ReturnedNotOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case Released:
+ Out << "Released";
+ break;
+
+ case ErrorDeallocGC:
+ Out << "-dealloc (GC)";
+ break;
+
+ case ErrorDeallocNotOwned:
+ Out << "-dealloc (not-owned)";
+ break;
+
+ case ErrorLeak:
+ Out << "Leaked";
+ break;
+
+ case ErrorLeakReturned:
+ Out << "Leaked (Bad naming)";
+ break;
+
+ case ErrorGCLeakReturned:
+ Out << "Leaked (GC-ed at return)";
+ break;
+
+ case ErrorUseAfterRelease:
+ Out << "Use-After-Release [ERROR]";
+ break;
+
+ case ErrorReleaseNotOwned:
+ Out << "Release of Not-Owned [ERROR]";
+ break;
+
+ case RefVal::ErrorOverAutorelease:
+ Out << "Over autoreleased";
+ break;
+
+ case RefVal::ErrorReturnedNotOwned:
+ Out << "Non-owned object returned instead of owned";
+ break;
+ }
+
+ if (ACnt) {
+ Out << " [ARC +" << ACnt << ']';
+ }
+}
+} //end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// RefBindings - State used to track object reference counts.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
+
+namespace clang {
+ template<>
+ struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
+ static void* GDMIndex() {
+ static int RefBIndex = 0;
+ return &RefBIndex;
+ }
+ };
+}
+
+//===----------------------------------------------------------------------===//
+// Summaries
+//===----------------------------------------------------------------------===//
+
+namespace {
class VISIBILITY_HIDDEN RetainSummary {
/// Args - an ordered vector of (index, ArgEffect) pairs, where index
/// specifies the argument (starting from 0). This can be sparsely
@@ -757,7 +984,11 @@ public:
RetainSummary* getSummary(FunctionDecl* FD);
- RetainSummary* getInstanceMethodSummary(ObjCMessageExpr* ME,
+ RetainSummary *getInstanceMethodSummary(const ObjCMessageExpr *ME,
+ const GRState *state,
+ const LocationContext *LC);
+
+ RetainSummary* getInstanceMethodSummary(const ObjCMessageExpr* ME,
const ObjCInterfaceDecl* ID) {
return getInstanceMethodSummary(ME->getSelector(), ME->getClassName(),
ID, ME->getMethodDecl(), ME->getType());
@@ -773,7 +1004,7 @@ public:
const ObjCMethodDecl *MD,
QualType RetTy);
- RetainSummary *getClassMethodSummary(ObjCMessageExpr *ME) {
+ RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME) {
return getClassMethodSummary(ME->getSelector(), ME->getClassName(),
ME->getClassInfo().first,
ME->getMethodDecl(), ME->getType());
@@ -1306,7 +1537,7 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
E = MD->param_end(); I != E; ++I, ++i)
if (ParmVarDecl *PD = *I) {
QualType Ty = Ctx.getCanonicalType(PD->getType());
- if (Ty.getUnqualifiedType() == Ctx.VoidPtrTy)
+ if (Ty.getLocalUnqualifiedType() == Ctx.VoidPtrTy)
ScratchArgs = AF.Add(ScratchArgs, i, StopTracking);
}
}
@@ -1350,6 +1581,61 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
}
RetainSummary*
+RetainSummaryManager::getInstanceMethodSummary(const ObjCMessageExpr *ME,
+ const GRState *state,
+ const LocationContext *LC) {
+
+ // We need the type-information of the tracked receiver object
+ // Retrieve it from the state.
+ const Expr *Receiver = ME->getReceiver();
+ const ObjCInterfaceDecl* ID = 0;
+
+ // FIXME: Is this really working as expected? There are cases where
+ // we just use the 'ID' from the message expression.
+ SVal receiverV = state->getSValAsScalarOrLoc(Receiver);
+
+ // FIXME: Eventually replace the use of state->get<RefBindings> with
+ // a generic API for reasoning about the Objective-C types of symbolic
+ // objects.
+ if (SymbolRef Sym = receiverV.getAsLocSymbol())
+ if (const RefVal *T = state->get<RefBindings>(Sym))
+ if (const ObjCObjectPointerType* PT =
+ T->getType()->getAs<ObjCObjectPointerType>())
+ ID = PT->getInterfaceDecl();
+
+ // FIXME: this is a hack. This may or may not be the actual method
+ // that is called.
+ if (!ID) {
+ if (const ObjCObjectPointerType *PT =
+ Receiver->getType()->getAs<ObjCObjectPointerType>())
+ ID = PT->getInterfaceDecl();
+ }
+
+ // FIXME: The receiver could be a reference to a class, meaning that
+ // we should use the class method.
+ RetainSummary *Summ = getInstanceMethodSummary(ME, ID);
+
+ // Special-case: are we sending a mesage to "self"?
+ // This is a hack. When we have full-IP this should be removed.
+ if (isa<ObjCMethodDecl>(LC->getDecl())) {
+ if (const loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&receiverV)) {
+ // Get the region associated with 'self'.
+ if (const ImplicitParamDecl *SelfDecl = LC->getSelfDecl()) {
+ SVal SelfVal = state->getSVal(state->getRegion(SelfDecl, LC));
+ if (L->StripCasts() == SelfVal.getAsRegion()) {
+ // Update the summary to make the default argument effect
+ // 'StopTracking'.
+ Summ = copySummary(Summ);
+ Summ->setDefaultArgEffect(StopTracking);
+ }
+ }
+ }
+ }
+
+ return Summ ? Summ : getDefaultSummary();
+}
+
+RetainSummary*
RetainSummaryManager::getInstanceMethodSummary(Selector S,
IdentifierInfo *ClsName,
const ObjCInterfaceDecl* ID,
@@ -1569,230 +1855,6 @@ void RetainSummaryManager::InitializeMethodSummaries() {
}
//===----------------------------------------------------------------------===//
-// Reference-counting logic (typestate + counts).
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class VISIBILITY_HIDDEN RefVal {
-public:
- enum Kind {
- Owned = 0, // Owning reference.
- NotOwned, // Reference is not owned by still valid (not freed).
- Released, // Object has been released.
- ReturnedOwned, // Returned object passes ownership to caller.
- ReturnedNotOwned, // Return object does not pass ownership to caller.
- ERROR_START,
- ErrorDeallocNotOwned, // -dealloc called on non-owned object.
- ErrorDeallocGC, // Calling -dealloc with GC enabled.
- ErrorUseAfterRelease, // Object used after released.
- ErrorReleaseNotOwned, // Release of an object that was not owned.
- ERROR_LEAK_START,
- ErrorLeak, // A memory leak due to excessive reference counts.
- ErrorLeakReturned, // A memory leak due to the returning method not having
- // the correct naming conventions.
- ErrorGCLeakReturned,
- ErrorOverAutorelease,
- ErrorReturnedNotOwned
- };
-
-private:
- Kind kind;
- RetEffect::ObjKind okind;
- unsigned Cnt;
- unsigned ACnt;
- QualType T;
-
- RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
- : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
-
- RefVal(Kind k, unsigned cnt = 0)
- : kind(k), okind(RetEffect::AnyObj), Cnt(cnt), ACnt(0) {}
-
-public:
- Kind getKind() const { return kind; }
-
- RetEffect::ObjKind getObjKind() const { return okind; }
-
- unsigned getCount() const { return Cnt; }
- unsigned getAutoreleaseCount() const { return ACnt; }
- unsigned getCombinedCounts() const { return Cnt + ACnt; }
- void clearCounts() { Cnt = 0; ACnt = 0; }
- void setCount(unsigned i) { Cnt = i; }
- void setAutoreleaseCount(unsigned i) { ACnt = i; }
-
- QualType getType() const { return T; }
-
- // Useful predicates.
-
- static bool isError(Kind k) { return k >= ERROR_START; }
-
- static bool isLeak(Kind k) { return k >= ERROR_LEAK_START; }
-
- bool isOwned() const {
- return getKind() == Owned;
- }
-
- bool isNotOwned() const {
- return getKind() == NotOwned;
- }
-
- bool isReturnedOwned() const {
- return getKind() == ReturnedOwned;
- }
-
- bool isReturnedNotOwned() const {
- return getKind() == ReturnedNotOwned;
- }
-
- bool isNonLeakError() const {
- Kind k = getKind();
- return isError(k) && !isLeak(k);
- }
-
- static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
- unsigned Count = 1) {
- return RefVal(Owned, o, Count, 0, t);
- }
-
- static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
- unsigned Count = 0) {
- return RefVal(NotOwned, o, Count, 0, t);
- }
-
- // Comparison, profiling, and pretty-printing.
-
- bool operator==(const RefVal& X) const {
- return kind == X.kind && Cnt == X.Cnt && T == X.T && ACnt == X.ACnt;
- }
-
- RefVal operator-(size_t i) const {
- return RefVal(getKind(), getObjKind(), getCount() - i,
- getAutoreleaseCount(), getType());
- }
-
- RefVal operator+(size_t i) const {
- return RefVal(getKind(), getObjKind(), getCount() + i,
- getAutoreleaseCount(), getType());
- }
-
- RefVal operator^(Kind k) const {
- return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
- getType());
- }
-
- RefVal autorelease() const {
- return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
- getType());
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.AddInteger((unsigned) kind);
- ID.AddInteger(Cnt);
- ID.AddInteger(ACnt);
- ID.Add(T);
- }
-
- void print(llvm::raw_ostream& Out) const;
-};
-
-void RefVal::print(llvm::raw_ostream& Out) const {
- if (!T.isNull())
- Out << "Tracked Type:" << T.getAsString() << '\n';
-
- switch (getKind()) {
- default: assert(false);
- case Owned: {
- Out << "Owned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case NotOwned: {
- Out << "NotOwned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case ReturnedOwned: {
- Out << "ReturnedOwned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case ReturnedNotOwned: {
- Out << "ReturnedNotOwned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case Released:
- Out << "Released";
- break;
-
- case ErrorDeallocGC:
- Out << "-dealloc (GC)";
- break;
-
- case ErrorDeallocNotOwned:
- Out << "-dealloc (not-owned)";
- break;
-
- case ErrorLeak:
- Out << "Leaked";
- break;
-
- case ErrorLeakReturned:
- Out << "Leaked (Bad naming)";
- break;
-
- case ErrorGCLeakReturned:
- Out << "Leaked (GC-ed at return)";
- break;
-
- case ErrorUseAfterRelease:
- Out << "Use-After-Release [ERROR]";
- break;
-
- case ErrorReleaseNotOwned:
- Out << "Release of Not-Owned [ERROR]";
- break;
-
- case RefVal::ErrorOverAutorelease:
- Out << "Over autoreleased";
- break;
-
- case RefVal::ErrorReturnedNotOwned:
- Out << "Non-owned object returned instead of owned";
- break;
- }
-
- if (ACnt) {
- Out << " [ARC +" << ACnt << ']';
- }
-}
-
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// RefBindings - State used to track object reference counts.
-//===----------------------------------------------------------------------===//
-
-typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
-static int RefBIndex = 0;
-
-namespace clang {
- template<>
- struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
- static inline void* GDMIndex() { return &RefBIndex; }
- };
-}
-
-//===----------------------------------------------------------------------===//
// AutoreleaseBindings - State used to track objects in autorelease pools.
//===----------------------------------------------------------------------===//
@@ -3004,69 +3066,14 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst,
GRStmtNodeBuilder& Builder,
ObjCMessageExpr* ME,
ExplodedNode* Pred) {
- RetainSummary* Summ = 0;
-
- if (Expr* Receiver = ME->getReceiver()) {
- // We need the type-information of the tracked receiver object
- // Retrieve it from the state.
- const ObjCInterfaceDecl* ID = 0;
-
- // FIXME: Wouldn't it be great if this code could be reduced? It's just
- // a chain of lookups.
- // FIXME: Is this really working as expected? There are cases where
- // we just use the 'ID' from the message expression.
- const GRState* St = Builder.GetState(Pred);
- SVal V = St->getSValAsScalarOrLoc(Receiver);
-
- SymbolRef Sym = V.getAsLocSymbol();
-
- if (Sym) {
- if (const RefVal* T = St->get<RefBindings>(Sym)) {
- if (const ObjCObjectPointerType* PT =
- T->getType()->getAs<ObjCObjectPointerType>())
- ID = PT->getInterfaceDecl();
- }
- }
-
- // FIXME: this is a hack. This may or may not be the actual method
- // that is called.
- if (!ID) {
- if (const ObjCObjectPointerType *PT =
- Receiver->getType()->getAs<ObjCObjectPointerType>())
- ID = PT->getInterfaceDecl();
- }
-
- // FIXME: The receiver could be a reference to a class, meaning that
- // we should use the class method.
- Summ = Summaries.getInstanceMethodSummary(ME, ID);
-
- // Special-case: are we sending a mesage to "self"?
- // This is a hack. When we have full-IP this should be removed.
- if (isa<ObjCMethodDecl>(Pred->getLocationContext()->getDecl())) {
- if (Expr* Receiver = ME->getReceiver()) {
- SVal X = St->getSValAsScalarOrLoc(Receiver);
- if (loc::MemRegionVal* L = dyn_cast<loc::MemRegionVal>(&X)) {
- // Get the region associated with 'self'.
- const LocationContext *LC = Pred->getLocationContext();
- if (const ImplicitParamDecl *SelfDecl = LC->getSelfDecl()) {
- SVal SelfVal = St->getSVal(St->getRegion(SelfDecl, LC));
- if (L->getBaseRegion() == SelfVal.getAsRegion()) {
- // Update the summary to make the default argument effect
- // 'StopTracking'.
- Summ = Summaries.copySummary(Summ);
- Summ->setDefaultArgEffect(StopTracking);
- }
- }
- }
- }
- }
- }
- else
- Summ = Summaries.getClassMethodSummary(ME);
-
- if (!Summ)
- Summ = Summaries.getDefaultSummary();
+
+ RetainSummary *Summ =
+ ME->getReceiver()
+ ? Summaries.getInstanceMethodSummary(ME, Builder.GetState(Pred),
+ Pred->getLocationContext())
+ : Summaries.getClassMethodSummary(ME);
+ assert(Summ && "RetainSummary is null");
EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), *Summ,
ME->arg_begin(), ME->arg_end(), Pred);
}
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index cd4697f2f324..8e8c1e7b25ed 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_NO_RTTI 1)
add_clang_library(clangAnalysis
AnalysisContext.cpp
- AnalysisManager.cpp
+ ArrayBoundChecker.cpp
AttrNonNullChecker.cpp
BadCallChecker.cpp
BasicConstraintManager.cpp
@@ -15,27 +15,39 @@ add_clang_library(clangAnalysis
CFRefCount.cpp
CallGraph.cpp
CallInliner.cpp
+ CastToStructChecker.cpp
CheckDeadStores.cpp
CheckObjCDealloc.cpp
CheckObjCInstMethSignature.cpp
CheckObjCUnusedIVars.cpp
CheckSecuritySyntaxOnly.cpp
+ CheckSizeofPointer.cpp
DereferenceChecker.cpp
DivZeroChecker.cpp
Environment.cpp
ExplodedGraph.cpp
+ FixedAddressChecker.cpp
GRBlockCounter.cpp
GRCoreEngine.cpp
GRExprEngine.cpp
+ GRExprEngineExperimentalChecks.cpp
GRExprEngineInternalChecks.cpp
GRState.cpp
LiveVariables.cpp
+ MallocChecker.cpp
+ ManagerRegistry.cpp
MemRegion.cpp
NSAutoreleasePoolChecker.cpp
NSErrorChecker.cpp
PathDiagnostic.cpp
+ PointerArithChecker.cpp
+ PointerSubChecker.cpp
+ PthreadLockChecker.cpp
RangeConstraintManager.cpp
RegionStore.cpp
+ ReturnPointerRangeChecker.cpp
+ ReturnStackAddressChecker.cpp
+ ReturnUndefChecker.cpp
SVals.cpp
SValuator.cpp
SimpleConstraintManager.cpp
@@ -43,10 +55,11 @@ add_clang_library(clangAnalysis
Store.cpp
SymbolManager.cpp
UndefinedArgChecker.cpp
+ UndefinedArraySubscriptChecker.cpp
UndefinedAssignmentChecker.cpp
UninitializedValues.cpp
- ValueManager.cpp
VLASizeChecker.cpp
+ ValueManager.cpp
)
add_dependencies(clangAnalysis ClangDiagnosticAnalysis)
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index 17dc0685f82f..06e3317691e3 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -117,7 +117,7 @@ void CallGraph::print(llvm::raw_ostream &os) {
<< " calls:\n";
for (CallGraphNode::iterator CI = I->second->begin(),
CE = I->second->end(); CI != CE; ++CI) {
- os << " " << CI->second->getName().c_str();
+ os << " " << CI->second->getName();
}
os << '\n';
}
diff --git a/lib/Analysis/CastToStructChecker.cpp b/lib/Analysis/CastToStructChecker.cpp
new file mode 100644
index 000000000000..ccd4a3333e22
--- /dev/null
+++ b/lib/Analysis/CastToStructChecker.cpp
@@ -0,0 +1,77 @@
+//=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines CastToStructChecker, a builtin checker that checks for
+// assignment of a fixed address to a pointer.
+// This check corresponds to CWE-588.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN CastToStructChecker
+ : public CheckerVisitor<CastToStructChecker> {
+ BuiltinBug *BT;
+public:
+ CastToStructChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+};
+}
+
+void *CastToStructChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
+ const CastExpr *CE) {
+ const Expr *E = CE->getSubExpr();
+ ASTContext &Ctx = C.getASTContext();
+ QualType OrigTy = Ctx.getCanonicalType(E->getType());
+ QualType ToTy = Ctx.getCanonicalType(CE->getType());
+
+ PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
+ PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
+
+ if (!ToPTy || !OrigPTy)
+ return;
+
+ QualType OrigPointeeTy = OrigPTy->getPointeeType();
+ QualType ToPointeeTy = ToPTy->getPointeeType();
+
+ if (!ToPointeeTy->isStructureType())
+ return;
+
+ // We allow cast from void*.
+ if (OrigPointeeTy->isVoidType())
+ return;
+
+ // Now the cast-to-type is struct pointer, the original type is not void*.
+ if (!OrigPointeeTy->isRecordType()) {
+ if (ExplodedNode *N = C.GenerateNode(CE)) {
+ if (!BT)
+ BT = new BuiltinBug("Cast from non-struct type to struct type",
+ "Casting a non-structure type to a structure type "
+ "and accessing a field can lead to memory access "
+ "errors or data corruption.");
+ RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N);
+ R->addRange(CE->getSourceRange());
+ C.EmitReport(R);
+ }
+ }
+}
+
+void clang::RegisterCastToStructChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new CastToStructChecker());
+}
diff --git a/lib/Analysis/CheckSecuritySyntaxOnly.cpp b/lib/Analysis/CheckSecuritySyntaxOnly.cpp
index 9f0d059cb66e..f1b9c2194f8b 100644
--- a/lib/Analysis/CheckSecuritySyntaxOnly.cpp
+++ b/lib/Analysis/CheckSecuritySyntaxOnly.cpp
@@ -23,6 +23,7 @@ namespace {
class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
BugReporter &BR;
IdentifierInfo *II_gets;
+ IdentifierInfo *II_getpw;
enum { num_rands = 9 };
IdentifierInfo *II_rand[num_rands];
IdentifierInfo *II_random;
@@ -31,7 +32,7 @@ class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
public:
WalkAST(BugReporter &br) : BR(br),
- II_gets(0), II_rand(), II_random(0), II_setid() {}
+ II_gets(0), II_getpw(0), II_rand(), II_random(0), II_setid() {}
// Statement visitor methods.
void VisitCallExpr(CallExpr *CE);
@@ -47,6 +48,7 @@ public:
// Checker-specific methods.
void CheckLoopConditionForFloat(const ForStmt *FS);
void CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD);
+ void CheckCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
void CheckCall_rand(const CallExpr *CE, const FunctionDecl *FD);
void CheckCall_random(const CallExpr *CE, const FunctionDecl *FD);
void CheckUncheckedReturnValue(CallExpr *CE);
@@ -77,6 +79,7 @@ void WalkAST::VisitChildren(Stmt *S) {
void WalkAST::VisitCallExpr(CallExpr *CE) {
if (const FunctionDecl *FD = CE->getDirectCallee()) {
CheckCall_gets(CE, FD);
+ CheckCall_getpw(CE, FD);
CheckCall_rand(CE, FD);
CheckCall_random(CE, FD);
}
@@ -215,22 +218,23 @@ void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) {
// Check: Any use of 'gets' is insecure.
// Originally: <rdar://problem/6335715>
// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
+// CWE-242: Use of Inherently Dangerous Function
//===----------------------------------------------------------------------===//
void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
if (FD->getIdentifier() != GetIdentifier(II_gets, "gets"))
return;
- const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FD->getType());
- if (!FTP)
+ const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FD->getType());
+ if (!FPT)
return;
// Verify that the function takes a single argument.
- if (FTP->getNumArgs() != 1)
+ if (FPT->getNumArgs() != 1)
return;
// Is the argument a 'char*'?
- const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0));
+ const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
if (!PT)
return;
@@ -247,6 +251,44 @@ void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
}
//===----------------------------------------------------------------------===//
+// Check: Any use of 'getpwd' is insecure.
+// CWE-477: Use of Obsolete Functions
+//===----------------------------------------------------------------------===//
+
+void WalkAST::CheckCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
+ if (FD->getIdentifier() != GetIdentifier(II_getpw, "getpw"))
+ return;
+
+ const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FD->getType());
+ if (!FPT)
+ return;
+
+ // Verify that the function takes two arguments.
+ if (FPT->getNumArgs() != 2)
+ return;
+
+ // Verify the first argument type is integer.
+ if (!FPT->getArgType(0)->isIntegerType())
+ return;
+
+ // Verify the second argument type is char*.
+ const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(1));
+ if (!PT)
+ return;
+
+ if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+ return;
+
+ // Issue a warning.
+ SourceRange R = CE->getCallee()->getSourceRange();
+ BR.EmitBasicReport("Potential buffer overflow in call to 'getpw'",
+ "Security",
+ "The getpw() function is dangerous as it may overflow the "
+ "provided buffer. It is obsoleted by getpwuid().",
+ CE->getLocStart(), &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
// Check: Linear congruent random number generators should not be used
// Originally: <rdar://problem/63371000>
// CWE-338: Use of cryptographically weak prng
diff --git a/lib/Analysis/CheckSizeofPointer.cpp b/lib/Analysis/CheckSizeofPointer.cpp
new file mode 100644
index 000000000000..174beefbca45
--- /dev/null
+++ b/lib/Analysis/CheckSizeofPointer.cpp
@@ -0,0 +1,72 @@
+//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- 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 a check for unintended use of sizeof() on pointer
+// expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Analysis/LocalCheckers.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
+ BugReporter &BR;
+
+public:
+ WalkAST(BugReporter &br) : BR(br) {}
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ void VisitStmt(Stmt *S) { VisitChildren(S); }
+ void VisitChildren(Stmt *S);
+};
+}
+
+void WalkAST::VisitChildren(Stmt *S) {
+ for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+ if (Stmt *child = *I)
+ Visit(child);
+}
+
+// CWE-467: Use of sizeof() on a Pointer Type
+void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ if (!E->isSizeOf())
+ return;
+
+ // If an explicit type is used in the code, usually the coder knows what he is
+ // doing.
+ if (E->isArgumentType())
+ return;
+
+ QualType T = E->getTypeOfArgument();
+ if (T->isPointerType()) {
+
+ // Many false positives have the form 'sizeof *p'. This is reasonable
+ // because people know what they are doing when they intentionally
+ // dereference the pointer.
+ Expr *ArgEx = E->getArgumentExpr();
+ if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
+ return;
+
+ SourceRange R = ArgEx->getSourceRange();
+ BR.EmitBasicReport("Potential unintended use of sizeof() on pointer type",
+ "Logic",
+ "The code calls sizeof() on a pointer type. "
+ "This can produce an unexpected result.",
+ E->getLocStart(), &R, 1);
+ }
+}
+
+void clang::CheckSizeofPointer(const Decl *D, BugReporter &BR) {
+ WalkAST walker(BR);
+ walker.Visit(D->getBody());
+}
diff --git a/lib/Analysis/DereferenceChecker.cpp b/lib/Analysis/DereferenceChecker.cpp
index 33c85d507463..c3aa8f3a2879 100644
--- a/lib/Analysis/DereferenceChecker.cpp
+++ b/lib/Analysis/DereferenceChecker.cpp
@@ -13,100 +13,103 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/Checker.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "GRExprEngineInternalChecks.h"
using namespace clang;
-void *NullDerefChecker::getTag() {
- static int x = 0;
- return &x;
-}
-
-ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V,
- GRExprEngine &Eng) {
- Loc *LV = dyn_cast<Loc>(&V);
-
- // If the value is not a location, don't touch the node.
- if (!LV)
- return Pred;
-
- const GRState *NotNullState = state->Assume(*LV, true);
- const GRState *NullState = state->Assume(*LV, false);
+namespace {
+class VISIBILITY_HIDDEN DereferenceChecker : public Checker {
+ BuiltinBug *BT_null;
+ BuiltinBug *BT_undef;
+ llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
+public:
+ DereferenceChecker() : BT_null(0), BT_undef(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void VisitLocation(CheckerContext &C, const Stmt *S, SVal location);
- GRStmtNodeBuilder &Builder = Eng.getBuilder();
- BugReporter &BR = Eng.getBugReporter();
-
- // The explicit NULL case.
- if (NullState) {
- // Use the GDM to mark in the state what lval was null.
- const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV);
- NullState = NullState->set<GRState::NullDerefTag>(PersistentLV);
-
- ExplodedNode *N = Builder.generateNode(S, NullState, Pred,
- ProgramPoint::PostNullCheckFailedKind);
- if (N) {
- N->markAsSink();
-
- if (!NotNullState) { // Explicit null case.
- if (!BT)
- BT = new BuiltinBug(NULL, "Null dereference",
- "Dereference of null pointer");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
-
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetDerefExpr(N));
-
- BR.EmitReport(R);
-
- return 0;
- } else // Implicit null case.
- ImplicitNullDerefNodes.push_back(N);
- }
+ std::pair<ExplodedNode * const*, ExplodedNode * const*>
+ getImplicitNodes() const {
+ return std::make_pair(ImplicitNullDerefNodes.data(),
+ ImplicitNullDerefNodes.data() +
+ ImplicitNullDerefNodes.size());
}
-
- if (!NotNullState)
- return 0;
+};
+} // end anonymous namespace
- return Builder.generateNode(S, NotNullState, Pred,
- ProgramPoint::PostLocationChecksSucceedKind);
+void clang::RegisterDereferenceChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new DereferenceChecker());
}
-
-void *UndefDerefChecker::getTag() {
- static int x = 0;
- return &x;
+std::pair<ExplodedNode * const *, ExplodedNode * const *>
+clang::GetImplicitNullDereferences(GRExprEngine &Eng) {
+ DereferenceChecker *checker = Eng.getChecker<DereferenceChecker>();
+ if (!checker)
+ return std::make_pair((ExplodedNode * const *) 0,
+ (ExplodedNode * const *) 0);
+ return checker->getImplicitNodes();
}
-ExplodedNode *UndefDerefChecker::CheckLocation(const Stmt *S,
- ExplodedNode *Pred,
- const GRState *state, SVal V,
- GRExprEngine &Eng) {
- GRStmtNodeBuilder &Builder = Eng.getBuilder();
- BugReporter &BR = Eng.getBugReporter();
-
- if (V.isUndef()) {
- ExplodedNode *N = Builder.generateNode(S, state, Pred,
- ProgramPoint::PostUndefLocationCheckFailedKind);
+void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
+ SVal l) {
+ // Check for dereference of an undefined value.
+ if (l.isUndef()) {
+ ExplodedNode *N = C.GenerateNode(S, true);
if (N) {
- N->markAsSink();
+ if (!BT_undef)
+ BT_undef = new BuiltinBug("Dereference of undefined pointer value");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N);
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+ C.EmitReport(report);
+ }
+ return;
+ }
+
+ DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);
+
+ // Check for null dereferences.
+ if (!isa<Loc>(location))
+ return;
+
+ const GRState *state = C.getState();
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->Assume(location);
+
+ // The explicit NULL case.
+ if (nullState) {
+ // Generate an error node.
+ ExplodedNode *N = C.GenerateNode(S, nullState, true);
+ if (N) {
+ if (!notNullState) {
+ // We know that 'location' cannot be non-null. This is what
+ // we call an "explicit" null dereference.
+ if (!BT_null)
+ BT_null = new BuiltinBug("Null pointer dereference",
+ "Dereference of null pointer");
- if (!BT)
- BT = new BuiltinBug(0, "Undefined dereference",
- "Dereference of undefined pointer value");
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_null, BT_null->getDescription(), N);
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+
+ C.EmitReport(report);
+ return;
+ }
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetDerefExpr(N));
- BR.EmitReport(R);
+ // Otherwise, we have the case where the location could either be
+ // null or not-null. Record the error node as an "implicit" null
+ // dereference.
+ ImplicitNullDerefNodes.push_back(N);
}
- return 0;
}
-
- return Pred;
+
+ // From this point forward, we know that the location is not null.
+ assert(notNullState);
+ C.addTransition(state != nullState ? C.GenerateNode(S, notNullState) :
+ C.getPredecessor());
}
-
diff --git a/lib/Analysis/DivZeroChecker.cpp b/lib/Analysis/DivZeroChecker.cpp
index 9c2359f3b075..a8630f10088e 100644
--- a/lib/Analysis/DivZeroChecker.cpp
+++ b/lib/Analysis/DivZeroChecker.cpp
@@ -12,10 +12,25 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
using namespace clang;
+namespace {
+class VISIBILITY_HIDDEN DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
+ BuiltinBug *BT;
+public:
+ DivZeroChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+} // end anonymous namespace
+
+void clang::RegisterDivZeroChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new DivZeroChecker());
+}
+
void *DivZeroChecker::getTag() {
static int x;
return &x;
@@ -50,10 +65,10 @@ void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
if (stateZero && !stateNotZero) {
if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
if (!BT)
- BT = new BuiltinBug(0, "Division by zero");
+ BT = new BuiltinBug("Division by zero");
EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+ new EnhancedBugReport(*BT, BT->getDescription(), N);
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
bugreporter::GetDenomExpr(N));
diff --git a/lib/Analysis/ExplodedGraph.cpp b/lib/Analysis/ExplodedGraph.cpp
index 0dc81a4225a8..3b339ffc0dfe 100644
--- a/lib/Analysis/ExplodedGraph.cpp
+++ b/lib/Analysis/ExplodedGraph.cpp
@@ -273,7 +273,7 @@ ExplodedGraph::TrimInternal(const ExplodedNode* const* BeginSources,
ExplodedNode*
InterExplodedGraphMap::getMappedNode(const ExplodedNode* N) const {
- llvm::DenseMap<const ExplodedNode*, ExplodedNode*>::iterator I =
+ llvm::DenseMap<const ExplodedNode*, ExplodedNode*>::const_iterator I =
M.find(N);
return I == M.end() ? 0 : I->second;
diff --git a/lib/Analysis/FixedAddressChecker.cpp b/lib/Analysis/FixedAddressChecker.cpp
new file mode 100644
index 000000000000..80096dcb70d0
--- /dev/null
+++ b/lib/Analysis/FixedAddressChecker.cpp
@@ -0,0 +1,70 @@
+//=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines FixedAddressChecker, a builtin checker that checks for
+// assignment of a fixed address to a pointer.
+// This check corresponds to CWE-587.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN FixedAddressChecker
+ : public CheckerVisitor<FixedAddressChecker> {
+ BuiltinBug *BT;
+public:
+ FixedAddressChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+}
+
+void *FixedAddressChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ // Using a fixed address is not portable because that address will probably
+ // not be valid in all environments or platforms.
+
+ if (B->getOpcode() != BinaryOperator::Assign)
+ return;
+
+ QualType T = B->getType();
+ if (!T->isPointerType())
+ return;
+
+ const GRState *state = C.getState();
+
+ SVal RV = state->getSVal(B->getRHS());
+
+ if (!RV.isConstant() || RV.isZeroConstant())
+ return;
+
+ if (ExplodedNode *N = C.GenerateNode(B)) {
+ if (!BT)
+ BT = new BuiltinBug("Use fixed address",
+ "Using a fixed address is not portable because that "
+ "address will probably not be valid in all "
+ "environments or platforms.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
+ R->addRange(B->getRHS()->getSourceRange());
+ C.EmitReport(R);
+ }
+}
+
+void clang::RegisterFixedAddressChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new FixedAddressChecker());
+}
diff --git a/lib/Analysis/GRCoreEngine.cpp b/lib/Analysis/GRCoreEngine.cpp
index 87472472fdee..b99ba4f257ef 100644
--- a/lib/Analysis/GRCoreEngine.cpp
+++ b/lib/Analysis/GRCoreEngine.cpp
@@ -418,51 +418,38 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
Eng.WList->Enqueue(Succ, B, Idx+1);
}
-static inline PostStmt GetPostLoc(const Stmt* S, ProgramPoint::Kind K,
- const LocationContext *L, const void *tag) {
+static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
+ const LocationContext *LC, const void *tag){
switch (K) {
default:
- assert(false && "Invalid PostXXXKind.");
-
+ assert(false && "Unhandled ProgramPoint kind");
+ case ProgramPoint::PreStmtKind:
+ return PreStmt(S, LC, tag);
case ProgramPoint::PostStmtKind:
- return PostStmt(S, L, tag);
-
+ return PostStmt(S, LC, tag);
+ case ProgramPoint::PreLoadKind:
+ return PreLoad(S, LC, tag);
case ProgramPoint::PostLoadKind:
- return PostLoad(S, L, tag);
-
- case ProgramPoint::PostUndefLocationCheckFailedKind:
- return PostUndefLocationCheckFailed(S, L, tag);
-
- case ProgramPoint::PostLocationChecksSucceedKind:
- return PostLocationChecksSucceed(S, L, tag);
-
- case ProgramPoint::PostOutOfBoundsCheckFailedKind:
- return PostOutOfBoundsCheckFailed(S, L, tag);
-
- case ProgramPoint::PostNullCheckFailedKind:
- return PostNullCheckFailed(S, L, tag);
-
+ return PostLoad(S, LC, tag);
+ case ProgramPoint::PreStoreKind:
+ return PreStore(S, LC, tag);
case ProgramPoint::PostStoreKind:
- return PostStore(S, L, tag);
-
+ return PostStore(S, LC, tag);
case ProgramPoint::PostLValueKind:
- return PostLValue(S, L, tag);
-
+ return PostLValue(S, LC, tag);
case ProgramPoint::PostPurgeDeadSymbolsKind:
- return PostPurgeDeadSymbols(S, L, tag);
+ return PostPurgeDeadSymbols(S, LC, tag);
}
}
ExplodedNode*
-GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* State,
+GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
ExplodedNode* Pred,
ProgramPoint::Kind K,
const void *tag) {
- return K == ProgramPoint::PreStmtKind
- ? generateNodeInternal(PreStmt(S, Pred->getLocationContext(),tag),
- State, Pred)
- : generateNodeInternal(GetPostLoc(S, K, Pred->getLocationContext(), tag),
- State, Pred);
+
+ const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
+ return generateNodeInternal(L, state, Pred);
}
ExplodedNode*
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 212fea3a6bcc..26331776141f 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -293,9 +293,7 @@ void GRExprEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) {
Builder = &builder;
EntryNode = builder.getLastNode();
- // FIXME: Consolidate.
CurrentStmt = S;
- StateMgr.CurrentStmt = S;
// Set up our simple checks.
if (BatchAuditor)
@@ -320,9 +318,32 @@ void GRExprEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) {
SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols);
Builder->PurgingDeadSymbols = true;
- getTF().EvalDeadSymbols(Tmp, *this, *Builder, EntryNode, S,
+ // FIXME: This should soon be removed.
+ ExplodedNodeSet Tmp2;
+ getTF().EvalDeadSymbols(Tmp2, *this, *Builder, EntryNode, S,
CleanedState, SymReaper);
+ if (Checkers.empty())
+ Tmp = Tmp2;
+ else {
+ ExplodedNodeSet Tmp3;
+ ExplodedNodeSet *SrcSet = &Tmp2;
+ for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+ I != E; ++I) {
+ ExplodedNodeSet *DstSet = (I+1 == E) ? &Tmp
+ : (SrcSet == &Tmp2) ? &Tmp3
+ : &Tmp2;
+ DstSet->clear();
+ void *tag = I->first;
+ Checker *checker = I->second;
+ for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();
+ NI != NE; ++NI)
+ checker->GR_EvalDeadSymbols(*DstSet, *Builder, *this, S, *NI,
+ SymReaper, tag);
+ SrcSet = DstSet;
+ }
+ }
+
if (!Builder->BuildSinks && !Builder->HasGeneratedNode)
Tmp.Add(EntryNode);
}
@@ -353,8 +374,6 @@ void GRExprEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) {
CleanedState = NULL;
EntryNode = NULL;
- // FIXME: Consolidate.
- StateMgr.CurrentStmt = 0;
CurrentStmt = 0;
Builder = NULL;
@@ -878,6 +897,18 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, X, true));
}
+/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
+/// nodes when the control reaches the end of a function.
+void GRExprEngine::ProcessEndPath(GREndPathNodeBuilder& builder) {
+ getTF().EvalEndPath(*this, builder);
+ StateMgr.EndPath(builder.getState());
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
+ void *tag = I->first;
+ Checker *checker = I->second;
+ checker->EvalEndPath(builder, tag, *this);
+ }
+}
+
/// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a switch statement.
void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
@@ -1080,7 +1111,10 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
ExplodedNodeSet Tmp2;
Visit(Idx, *I1, Tmp2); // Evaluate the index.
- for (ExplodedNodeSet::iterator I2=Tmp2.begin(),E2=Tmp2.end();I2!=E2; ++I2) {
+ ExplodedNodeSet Tmp3;
+ CheckerVisit(A, Tmp3, Tmp2, true);
+
+ for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) {
const GRState* state = GetState(*I2);
SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
state->getSVal(Base));
@@ -1190,112 +1224,87 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
assert(Builder && "GRStmtNodeBuilder must be defined.");
// Evaluate the location (checks for bad dereferences).
- Pred = EvalLocation(StoreE, Pred, state, location, tag);
+ ExplodedNodeSet Tmp;
+ EvalLocation(Tmp, StoreE, Pred, state, location, tag, false);
- if (!Pred)
+ if (Tmp.empty())
return;
- assert (!location.isUndef());
- state = GetState(Pred);
+ assert(!location.isUndef());
+ SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind,
+ ProgramPoint::PostStoreKind);
+ SaveAndRestore<const void*> OldTag(Builder->Tag, tag);
+
// Proceed with the store.
- SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);
- SaveAndRestore<const void*> OldTag(Builder->Tag);
- Builder->PointKind = ProgramPoint::PostStoreKind;
- Builder->Tag = tag;
- EvalBind(Dst, AssignE, StoreE, Pred, state, location, Val);
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
+ EvalBind(Dst, AssignE, StoreE, *NI, GetState(*NI), location, Val);
}
-void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
const GRState* state, SVal location,
- const void *tag) {
+ const void *tag, QualType LoadTy) {
// Evaluate the location (checks for bad dereferences).
- Pred = EvalLocation(Ex, Pred, state, location, tag);
+ ExplodedNodeSet Tmp;
+ EvalLocation(Tmp, Ex, Pred, state, location, tag, true);
- if (!Pred)
+ if (Tmp.empty())
return;
-
- state = GetState(Pred);
+
+ assert(!location.isUndef());
+
+ SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);
+ SaveAndRestore<const void*> OldTag(Builder->Tag);
// Proceed with the load.
- ProgramPoint::Kind K = ProgramPoint::PostLoadKind;
-
- // FIXME: Currently symbolic analysis "generates" new symbols
- // for the contents of values. We need a better approach.
-
- if (location.isUnknown()) {
- // This is important. We must nuke the old binding.
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, UnknownVal()),
- K, tag);
- }
- else {
- SVal V = state->getSVal(cast<Loc>(location), Ex->getType());
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V), K, tag);
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
+ state = GetState(*NI);
+ if (location.isUnknown()) {
+ // This is important. We must nuke the old binding.
+ MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, UnknownVal()),
+ ProgramPoint::PostLoadKind, tag);
+ }
+ else {
+ SVal V = state->getSVal(cast<Loc>(location), LoadTy.isNull() ?
+ Ex->getType() : LoadTy);
+ MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, V), ProgramPoint::PostLoadKind,
+ tag);
+ }
}
}
-ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
- const GRState* state, SVal location,
- const void *tag) {
-
- SaveAndRestore<const void*> OldTag(Builder->Tag);
- Builder->Tag = tag;
+void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, Stmt *S,
+ ExplodedNode* Pred,
+ const GRState* state, SVal location,
+ const void *tag, bool isLoad) {
- if (location.isUnknown() || Checkers.empty())
- return Pred;
-
-
- for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
- {
- Pred = I->second->CheckLocation(Ex, Pred, state, location, *this);
- if (!Pred)
- break;
+ if (location.isUnknown() || Checkers.empty()) {
+ Dst.Add(Pred);
+ return;
}
- return Pred;
-
- // FIXME: Temporarily disable out-of-bounds checking until we make
- // the logic reflect recent changes to CastRegion and friends.
-#if 0
- // Check for out-of-bound array access.
- if (isa<loc::MemRegionVal>(LV)) {
- const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
- if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
- // Get the index of the accessed element.
- SVal Idx = ER->getIndex();
- // Get the extent of the array.
- SVal NumElements = getStoreManager().getSizeInElements(StNotNull,
- ER->getSuperRegion());
-
- const GRState * StInBound = StNotNull->AssumeInBound(Idx, NumElements,
- true);
- const GRState* StOutBound = StNotNull->AssumeInBound(Idx, NumElements,
- false);
-
- if (StOutBound) {
- // Report warning. Make sink node manually.
- ExplodedNode* OOBNode =
- Builder->generateNode(Ex, StOutBound, Pred,
- ProgramPoint::PostOutOfBoundsCheckFailedKind);
-
- if (OOBNode) {
- OOBNode->markAsSink();
-
- if (StInBound)
- ImplicitOOBMemAccesses.insert(OOBNode);
- else
- ExplicitOOBMemAccesses.insert(OOBNode);
- }
- }
-
- if (!StInBound)
- return NULL;
-
- StNotNull = StInBound;
- }
+ ExplodedNodeSet Src, Tmp;
+ Src.Add(Pred);
+ ExplodedNodeSet *PrevSet = &Src;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
+ : (PrevSet == &Tmp) ? &Src : &Tmp;
+
+ CurrSet->clear();
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI)
+ checker->GR_VisitLocation(*CurrSet, *Builder, *this, S, *NI, state,
+ location, tag, isLoad);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
}
-#endif
}
//===----------------------------------------------------------------------===//
@@ -1311,8 +1320,7 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- CallExpr* CE, SVal L,
- ExplodedNode* Pred) {
+ CallExpr* CE, ExplodedNode* Pred) {
// Not enough arguments to match OSAtomicCompareAndSwap?
if (CE->getNumArgs() != 3)
@@ -1354,7 +1362,13 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst,
const GRState *state = Pred->getState();
ExplodedNodeSet Tmp;
SVal location = state->getSVal(theValueExpr);
- Engine.EvalLoad(Tmp, theValueExpr, Pred, state, location, OSAtomicLoadTag);
+ // Here we should use the value type of the region as the load type.
+ const MemRegion *R = location.getAsRegion();
+ QualType LoadTy;
+ if (R)
+ LoadTy = cast<TypedRegion>(R)->getValueType(C);
+ Engine.EvalLoad(Tmp, theValueExpr, Pred, state, location, OSAtomicLoadTag,
+ LoadTy);
for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end();
I != E; ++I) {
@@ -1432,7 +1446,7 @@ static bool EvalOSAtomic(ExplodedNodeSet& Dst,
// Check for compare and swap.
if (strncmp(FName, "OSAtomicCompareAndSwap", 22) == 0 ||
strncmp(FName, "objc_atomicCompareAndSwap", 25) == 0)
- return EvalOSAtomicCompareAndSwap(Dst, Engine, Builder, CE, L, Pred);
+ return EvalOSAtomicCompareAndSwap(Dst, Engine, Builder, CE, Pred);
// FIXME: Other atomics.
return false;
@@ -1521,17 +1535,6 @@ bool GRExprEngine::EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE,
return false;
}
-void GRExprEngine::EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L,
- ExplodedNode* Pred) {
- assert (Builder && "GRStmtNodeBuilder must be defined.");
-
- // FIXME: Allow us to chain together transfer functions.
- if (EvalOSAtomic(Dst, *this, *Builder, CE, L, Pred))
- return;
-
- getTF().EvalCall(Dst, *this, *Builder, CE, L, Pred);
-}
-
void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
CallExpr::arg_iterator AI,
CallExpr::arg_iterator AE,
@@ -1609,17 +1612,25 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
continue;
// Dispatch to the plug-in transfer function.
-
- unsigned size = Dst.size();
SaveOr OldHasGen(Builder->HasGeneratedNode);
- EvalCall(Dst, CE, L, *DI);
+ Pred = *DI;
+
+ // Dispatch to transfer function logic to handle the call itself.
+ // FIXME: Allow us to chain together transfer functions.
+ assert(Builder && "GRStmtNodeBuilder must be defined.");
+ ExplodedNodeSet DstTmp;
+
+ if (!EvalOSAtomic(DstTmp, *this, *Builder, CE, L, Pred))
+ getTF().EvalCall(DstTmp, *this, *Builder, CE, L, Pred);
// Handle the case where no nodes where generated. Auto-generate that
// contains the updated state if we aren't generating sinks.
-
- if (!Builder->BuildSinks && Dst.size() == size &&
+ if (!Builder->BuildSinks && DstTmp.empty() &&
!Builder->HasGeneratedNode)
- MakeNode(Dst, CE, *DI, state);
+ MakeNode(DstTmp, CE, Pred, state);
+
+ // Perform the post-condition check of the CallExpr.
+ CheckerVisit(CE, Dst, DstTmp, false);
}
}
@@ -1749,46 +1760,47 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
ExplodedNode* Pred, ExplodedNodeSet& Dst,
SVal ElementV) {
-
-
- // Get the current state. Use 'EvalLocation' to determine if it is a null
- // pointer, etc.
+ // Check if the location we are writing back to is a null pointer.
Stmt* elem = S->getElement();
-
- Pred = EvalLocation(elem, Pred, GetState(Pred), ElementV);
- if (!Pred)
+ ExplodedNodeSet Tmp;
+ EvalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
+
+ if (Tmp.empty())
return;
+
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
+ Pred = *NI;
+ const GRState *state = GetState(Pred);
+
+ // Handle the case where the container still has elements.
+ SVal TrueV = ValMgr.makeTruthVal(1);
+ const GRState *hasElems = state->BindExpr(S, TrueV);
+
+ // Handle the case where the container has no elements.
+ SVal FalseV = ValMgr.makeTruthVal(0);
+ const GRState *noElems = state->BindExpr(S, FalseV);
+
+ if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
+ if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
+ // FIXME: The proper thing to do is to really iterate over the
+ // container. We will do this with dispatch logic to the store.
+ // For now, just 'conjure' up a symbolic value.
+ QualType T = R->getValueType(getContext());
+ assert(Loc::IsLocType(T));
+ unsigned Count = Builder->getCurrentBlockCount();
+ SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
+ SVal V = ValMgr.makeLoc(Sym);
+ hasElems = hasElems->bindLoc(ElementV, V);
+
+ // Bind the location to 'nil' on the false branch.
+ SVal nilV = ValMgr.makeIntVal(0, T);
+ noElems = noElems->bindLoc(ElementV, nilV);
+ }
- const GRState *state = GetState(Pred);
-
- // Handle the case where the container still has elements.
- SVal TrueV = ValMgr.makeTruthVal(1);
- const GRState *hasElems = state->BindExpr(S, TrueV);
-
- // Handle the case where the container has no elements.
- SVal FalseV = ValMgr.makeTruthVal(0);
- const GRState *noElems = state->BindExpr(S, FalseV);
-
- if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
- if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
- // FIXME: The proper thing to do is to really iterate over the
- // container. We will do this with dispatch logic to the store.
- // For now, just 'conjure' up a symbolic value.
- QualType T = R->getValueType(getContext());
- assert (Loc::IsLocType(T));
- unsigned Count = Builder->getCurrentBlockCount();
- SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
- SVal V = ValMgr.makeLoc(Sym);
- hasElems = hasElems->bindLoc(ElementV, V);
-
- // Bind the location to 'nil' on the false branch.
- SVal nilV = ValMgr.makeIntVal(0, T);
- noElems = noElems->bindLoc(ElementV, nilV);
- }
-
- // Create the new nodes.
- MakeNode(Dst, S, Pred, hasElems);
- MakeNode(Dst, S, Pred, noElems);
+ // Create the new nodes.
+ MakeNode(Dst, S, Pred, hasElems);
+ MakeNode(Dst, S, Pred, noElems);
+ }
}
//===----------------------------------------------------------------------===//
@@ -2035,7 +2047,8 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst){
+void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst){
ExplodedNodeSet S1;
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
@@ -2048,16 +2061,18 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, Exploded
else
Visit(Ex, Pred, S1);
+ ExplodedNodeSet S2;
+ CheckerVisit(CastE, S2, S1, true);
+
// Check for casting to "void".
if (T->isVoidType()) {
- for (ExplodedNodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1)
- Dst.Add(*I1);
-
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
+ Dst.Add(*I);
return;
}
- for (ExplodedNodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
- ExplodedNode* N = *I1;
+ 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);
@@ -2107,23 +2122,12 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
else
Tmp.Add(Pred);
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ ExplodedNodeSet Tmp2;
+ CheckerVisit(DS, Tmp2, Tmp, true);
+
+ for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) {
ExplodedNode *N = *I;
- const GRState *state;
-
- for (CheckersOrdered::iterator CI = Checkers.begin(), CE = Checkers.end();
- CI != CE; ++CI) {
- state = GetState(N);
- N = CI->second->CheckType(getContext().getCanonicalType(VD->getType()),
- N, state, DS, *this);
- if (!N)
- break;
- }
-
- if (!N)
- continue;
-
- state = GetState(N);
+ const GRState *state = GetState(N);
// Decls without InitExpr are not initialized explicitly.
const LocationContext *LC = N->getLocationContext();
@@ -2628,63 +2632,37 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
}
-void GRExprEngine::EvalReturn(ExplodedNodeSet& Dst, ReturnStmt* S,
- ExplodedNode* Pred) {
- assert (Builder && "GRStmtNodeBuilder must be defined.");
-
- unsigned size = Dst.size();
-
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- getTF().EvalReturn(Dst, *this, *Builder, S, Pred);
-
- // Handle the case where no nodes where generated.
-
- if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode)
- MakeNode(Dst, S, Pred, GetState(Pred));
-}
-
-void GRExprEngine::VisitReturnStmt(ReturnStmt* S, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
-
- Expr* R = S->getRetValue();
-
- if (!R) {
- EvalReturn(Dst, S, Pred);
- return;
+void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+
+ ExplodedNodeSet Src;
+ if (Expr *RetE = RS->getRetValue()) {
+ Visit(RetE, Pred, Src);
}
+ else {
+ Src.Add(Pred);
+ }
+
+ ExplodedNodeSet CheckedSet;
+ CheckerVisit(RS, CheckedSet, Src, true);
+
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I != E; ++I) {
- ExplodedNodeSet Tmp;
- Visit(R, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
- SVal X = (*I)->getState()->getSVal(R);
-
- // Check if we return the address of a stack variable.
- if (isa<loc::MemRegionVal>(X)) {
- // Determine if the value is on the stack.
- const MemRegion* R = cast<loc::MemRegionVal>(&X)->getRegion();
-
- if (R && R->hasStackStorage()) {
- // Create a special node representing the error.
- if (ExplodedNode* N = Builder->generateNode(S, GetState(*I), *I)) {
- N->markAsSink();
- RetsStackAddr.insert(N);
- }
- continue;
- }
- }
- // Check if we return an undefined value.
- else if (X.isUndef()) {
- if (ExplodedNode* N = Builder->generateNode(S, GetState(*I), *I)) {
- N->markAsSink();
- RetsUndef.insert(N);
- }
- continue;
- }
-
- EvalReturn(Dst, S, *I);
+ assert(Builder && "GRStmtNodeBuilder must be defined.");
+
+ Pred = *I;
+ unsigned size = Dst.size();
+
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ SaveOr OldHasGen(Builder->HasGeneratedNode);
+
+ getTF().EvalReturn(Dst, *this, *Builder, RS, Pred);
+
+ // Handle the case where no nodes where generated.
+ if (!Builder->BuildSinks && Dst.size() == size &&
+ !Builder->HasGeneratedNode)
+ MakeNode(Dst, RS, Pred, GetState(Pred));
}
}
@@ -2878,7 +2856,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
//===----------------------------------------------------------------------===//
Checker *GRExprEngine::lookupChecker(void *tag) const {
- CheckerMap::iterator I = CheckerM.find(tag);
+ CheckerMap::const_iterator I = CheckerM.find(tag);
return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;
}
@@ -2898,6 +2876,9 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
// work.
static std::string getNodeAttributes(const ExplodedNode* N, void*) {
+#if 0
+ // FIXME: Replace with a general scheme to tell if the node is
+ // an error node.
if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
GraphPrintCheckerState->isExplicitNullDeref(N) ||
GraphPrintCheckerState->isUndefDeref(N) ||
@@ -2907,6 +2888,7 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
GraphPrintCheckerState->isBadCall(N) ||
GraphPrintCheckerState->isUndefArg(N))
return "color=\"red\",style=\"filled\"";
+#endif
if (GraphPrintCheckerState->isNoReturnCall(N))
return "color=\"blue\",style=\"filled\"";
@@ -2957,11 +2939,10 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
Out << "\\lPostStore\\l";
else if (isa<PostLValue>(Loc))
Out << "\\lPostLValue\\l";
- else if (isa<PostLocationChecksSucceed>(Loc))
- Out << "\\lPostLocationChecksSucceed\\l";
- else if (isa<PostNullCheckFailed>(Loc))
- Out << "\\lPostNullCheckFailed\\l";
+#if 0
+ // FIXME: Replace with a general scheme to determine
+ // the name of the check.
if (GraphPrintCheckerState->isImplicitNullDeref(N))
Out << "\\|Implicit-Null Dereference.\\l";
else if (GraphPrintCheckerState->isExplicitNullDeref(N))
@@ -2978,6 +2959,7 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
Out << "\\|Call to NULL/Undefined.";
else if (GraphPrintCheckerState->isUndefArg(N))
Out << "\\|Argument in call is undefined";
+#endif
break;
}
@@ -3039,9 +3021,13 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
Out << "\\l";
}
+#if 0
+ // FIXME: Replace with a general scheme to determine
+ // the name of the check.
if (GraphPrintCheckerState->isUndefControlFlow(N)) {
Out << "\\|Control-flow based on\\lUndefined value.\\l";
}
+#endif
}
}
diff --git a/lib/Analysis/GRExprEngineExperimentalChecks.cpp b/lib/Analysis/GRExprEngineExperimentalChecks.cpp
new file mode 100644
index 000000000000..2fb7e9fa482f
--- /dev/null
+++ b/lib/Analysis/GRExprEngineExperimentalChecks.cpp
@@ -0,0 +1,38 @@
+//=-- GRExprEngineExperimentalChecks.h ------------------------------*- 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 functions to instantiate and register experimental
+// checks in GRExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "GRExprEngineExperimentalChecks.h"
+#include "clang/Analysis/LocalCheckers.h"
+
+using namespace clang;
+
+void clang::RegisterExperimentalChecks(GRExprEngine &Eng) {
+ // These are checks that never belong as internal checks
+ // within GRExprEngine.
+ RegisterPthreadLockChecker(Eng);
+ RegisterMallocChecker(Eng);
+}
+
+void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) {
+ // These are internal checks that should eventually migrate to
+ // RegisterInternalChecks() once they have been further tested.
+
+ // Note that this must be registered after ReturnStackAddresEngsChecker.
+ RegisterReturnPointerRangeChecker(Eng);
+ RegisterPointerSubChecker(Eng);
+ RegisterPointerArithChecker(Eng);
+ RegisterCastToStructChecker(Eng);
+ RegisterArrayBoundChecker(Eng);
+}
diff --git a/lib/Analysis/GRExprEngineExperimentalChecks.h b/lib/Analysis/GRExprEngineExperimentalChecks.h
new file mode 100644
index 000000000000..9a9da32e556e
--- /dev/null
+++ b/lib/Analysis/GRExprEngineExperimentalChecks.h
@@ -0,0 +1,26 @@
+//=-- GRExprEngineExperimentalChecks.h ------------------------------*- 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 functions to instantiate and register experimental
+// checks in GRExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GREXPRENGINE_EXPERIMENTAL_CHECKS
+#define LLVM_CLANG_GREXPRENGINE_EXPERIMENTAL_CHECKS
+
+namespace clang {
+
+class GRExprEngine;
+
+void RegisterPthreadLockChecker(GRExprEngine &Eng);
+void RegisterMallocChecker(GRExprEngine &Eng);
+
+} // end clang namespace
+#endif
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index 695f0b02e597..d0f60fde5b1b 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -12,16 +12,11 @@
//
//===----------------------------------------------------------------------===//
+#include "GRExprEngineInternalChecks.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
-#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
-#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
-#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
-#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
-#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
-#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Compiler.h"
@@ -290,79 +285,6 @@ public:
}
};
-class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
-public:
- RetStack(GRExprEngine* eng)
- : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
- End = Eng.ret_stackaddr_end(); I!=End; ++I) {
-
- ExplodedNode* N = *I;
- const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
- const Expr* E = cast<ReturnStmt>(S)->getRetValue();
- assert(E && "Return expression cannot be NULL");
-
- // Get the value associated with E.
- loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
-
- // Generate a report for this bug.
- std::string buf;
- llvm::raw_string_ostream os(buf);
- SourceRange R;
-
- // Check if the region is a compound literal.
- if (const CompoundLiteralRegion* CR =
- dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
-
- const CompoundLiteralExpr* CL = CR->getLiteralExpr();
- os << "Address of stack memory associated with a compound literal "
- "declared on line "
- << BR.getSourceManager()
- .getInstantiationLineNumber(CL->getLocStart())
- << " returned.";
-
- R = CL->getSourceRange();
- }
- else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
- const Expr* ARE = AR->getExpr();
- SourceLocation L = ARE->getLocStart();
- R = ARE->getSourceRange();
-
- os << "Address of stack memory allocated by call to alloca() on line "
- << BR.getSourceManager().getInstantiationLineNumber(L)
- << " returned.";
- }
- else {
- os << "Address of stack memory associated with local variable '"
- << V.getRegion()->getString() << "' returned.";
- }
-
- RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
- report->addRange(E->getSourceRange());
- if (R.isValid()) report->addRange(R);
- BR.EmitReport(report);
- }
- }
-};
-
-class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
-public:
- RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
- "Undefined or garbage value returned to caller") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
- }
-};
-
class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
struct VISIBILITY_HIDDEN FindUndefExpr {
GRStateManager& VM;
@@ -439,17 +361,6 @@ public:
}
};
-class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
-public:
- OutOfBoundMemoryAccess(GRExprEngine* eng)
- : BuiltinBug(eng,"Out-of-bounds memory access",
- "Load or store into an out-of-bound memory position.") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
- }
-};
-
} // end clang namespace
//===----------------------------------------------------------------------===//
@@ -464,11 +375,8 @@ void GRExprEngine::RegisterInternalChecks() {
// to 'FlushReports' from BugReporter.
BR.Register(new UndefBranch(this));
BR.Register(new UndefResult(this));
- BR.Register(new RetStack(this));
- BR.Register(new RetUndef(this));
BR.Register(new BadMsgExprArg(this));
BR.Register(new BadReceiver(this));
- BR.Register(new OutOfBoundMemoryAccess(this));
BR.Register(new NilReceiverStructRet(this));
BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
@@ -476,14 +384,17 @@ void GRExprEngine::RegisterInternalChecks() {
// explicitly registered with the BugReporter. If they issue any BugReports,
// their associated BugType will get registered with the BugReporter
// automatically. Note that the check itself is owned by the GRExprEngine
- // object.
- registerCheck(new AttrNonNullChecker());
- registerCheck(new UndefinedArgChecker());
+ // object.
registerCheck(new UndefinedAssignmentChecker());
- registerCheck(new BadCallChecker());
- registerCheck(new DivZeroChecker());
- registerCheck(new UndefDerefChecker());
- registerCheck(new NullDerefChecker());
- registerCheck(new UndefSizedVLAChecker());
- registerCheck(new ZeroSizedVLAChecker());
+
+ RegisterAttrNonNullChecker(*this);
+ RegisterUndefinedArgChecker(*this);
+ RegisterBadCallChecker(*this);
+ RegisterDereferenceChecker(*this);
+ RegisterVLASizeChecker(*this);
+ RegisterDivZeroChecker(*this);
+ RegisterReturnStackAddressChecker(*this);
+ RegisterReturnUndefChecker(*this);
+ RegisterFixedAddressChecker(*this);
+ RegisterUndefinedArraySubscriptChecker(*this);
}
diff --git a/lib/Analysis/GRExprEngineInternalChecks.h b/lib/Analysis/GRExprEngineInternalChecks.h
new file mode 100644
index 000000000000..a9077bf75715
--- /dev/null
+++ b/lib/Analysis/GRExprEngineInternalChecks.h
@@ -0,0 +1,39 @@
+//=-- GRExprEngineInternalChecks.h- Builtin GRExprEngine Checks -----*- 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 functions to instantiate and register the "built-in"
+// checks in GRExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GREXPRENGINE_INTERNAL_CHECKS
+#define LLVM_CLANG_GREXPRENGINE_INTERNAL_CHECKS
+
+namespace clang {
+
+class GRExprEngine;
+
+void RegisterAttrNonNullChecker(GRExprEngine &Eng);
+void RegisterBadCallChecker(GRExprEngine &Eng);
+void RegisterDereferenceChecker(GRExprEngine &Eng);
+void RegisterDivZeroChecker(GRExprEngine &Eng);
+void RegisterReturnPointerRangeChecker(GRExprEngine &Eng);
+void RegisterReturnStackAddressChecker(GRExprEngine &Eng);
+void RegisterReturnUndefChecker(GRExprEngine &Eng);
+void RegisterVLASizeChecker(GRExprEngine &Eng);
+void RegisterPointerSubChecker(GRExprEngine &Eng);
+void RegisterPointerArithChecker(GRExprEngine &Eng);
+void RegisterFixedAddressChecker(GRExprEngine &Eng);
+void RegisterCastToStructChecker(GRExprEngine &Eng);
+void RegisterUndefinedArgChecker(GRExprEngine &Eng);
+void RegisterArrayBoundChecker(GRExprEngine &Eng);
+void RegisterUndefinedArraySubscriptChecker(GRExprEngine &Eng);
+
+} // end clang namespace
+#endif
diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp
index f269824d5477..23ee0b2258bd 100644
--- a/lib/Analysis/GRState.cpp
+++ b/lib/Analysis/GRState.cpp
@@ -332,9 +332,3 @@ bool GRStateManager::isEqual(const GRState* state, const Expr* Ex,
bool GRStateManager::isEqual(const GRState* state, const Expr* Ex, uint64_t x) {
return isEqual(state, Ex, getBasicVals().getValue(x, Ex->getType()));
}
-
-//===----------------------------------------------------------------------===//
-// Persistent values for indexing into the Generic Data Map.
-
-int GRState::NullDerefTag::TagInt = 0;
-
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index ae78d1f35ff6..2510445a7f31 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -18,6 +18,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
#include "clang/Analysis/FlowSensitive/DataflowSolver.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
@@ -301,10 +302,9 @@ void LiveVariables::runOnAllBlocks(const CFG& cfg,
LiveVariables::ObserverTy* Obs,
bool recordStmtValues) {
Solver S(*this);
- ObserverTy* OldObserver = getAnalysisData().Observer;
- getAnalysisData().Observer = Obs;
+ SaveAndRestore<LiveVariables::ObserverTy*> SRObs(getAnalysisData().Observer,
+ Obs);
S.runOnAllBlocks(cfg, recordStmtValues);
- getAnalysisData().Observer = OldObserver;
}
//===----------------------------------------------------------------------===//
@@ -333,7 +333,7 @@ bool LiveVariables::isLive(const Stmt* Loc, const VarDecl* D) const {
// printing liveness state for debugging
//
-void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {
+void LiveVariables::dumpLiveness(const ValTy& V, const SourceManager& SM) const {
const AnalysisDataTy& AD = getAnalysisData();
for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),
@@ -345,8 +345,8 @@ void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {
}
}
-void LiveVariables::dumpBlockLiveness(SourceManager& M) const {
- for (BlockDataMapTy::iterator I = getBlockDataMap().begin(),
+void LiveVariables::dumpBlockLiveness(const SourceManager& M) const {
+ for (BlockDataMapTy::const_iterator I = getBlockDataMap().begin(),
E = getBlockDataMap().end(); I!=E; ++I) {
llvm::errs() << "\n[ B" << I->first->getBlockID()
<< " (live variables at block exit) ]\n";
diff --git a/lib/Analysis/MallocChecker.cpp b/lib/Analysis/MallocChecker.cpp
new file mode 100644
index 000000000000..93e708332ed7
--- /dev/null
+++ b/lib/Analysis/MallocChecker.cpp
@@ -0,0 +1,218 @@
+//=== MallocChecker.cpp - A malloc/free checker -------------------*- 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 malloc/free checker, which checks for potential memory
+// leaks, double free, and use-after-free problems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineExperimentalChecks.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
+#include "clang/Analysis/PathSensitive/GRStateTrait.h"
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+using namespace clang;
+
+namespace {
+
+struct RefState {
+ enum Kind { Allocated, Released, Escaped } K;
+ const Stmt *S;
+
+ RefState(Kind k, const Stmt *s) : K(k), S(s) {}
+
+ bool isAllocated() const { return K == Allocated; }
+ bool isReleased() const { return K == Released; }
+ bool isEscaped() const { return K == Escaped; }
+
+ bool operator==(const RefState &X) const {
+ return K == X.K && S == X.S;
+ }
+
+ static RefState getAllocated(const Stmt *s) { return RefState(Allocated, s); }
+ static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
+ static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(K);
+ ID.AddPointer(S);
+ }
+};
+
+class VISIBILITY_HIDDEN RegionState {};
+
+class VISIBILITY_HIDDEN MallocChecker : public CheckerVisitor<MallocChecker> {
+ BuiltinBug *BT_DoubleFree;
+ BuiltinBug *BT_Leak;
+ IdentifierInfo *II_malloc;
+ IdentifierInfo *II_free;
+
+public:
+ MallocChecker() : BT_DoubleFree(0), BT_Leak(0), II_malloc(0), II_free(0) {}
+ static void *getTag();
+ void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void EvalDeadSymbols(CheckerContext &C,const Stmt *S,SymbolReaper &SymReaper);
+ void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
+private:
+ void MallocMem(CheckerContext &C, const CallExpr *CE);
+ void FreeMem(CheckerContext &C, const CallExpr *CE);
+};
+}
+
+namespace clang {
+ template <>
+ struct GRStateTrait<RegionState>
+ : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, RefState> > {
+ static void *GDMIndex() { return MallocChecker::getTag(); }
+ };
+}
+
+void clang::RegisterMallocChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new MallocChecker());
+}
+
+void *MallocChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void MallocChecker::PostVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const FunctionDecl *FD = CE->getDirectCallee();
+ if (!FD)
+ return;
+
+ ASTContext &Ctx = C.getASTContext();
+ if (!II_malloc)
+ II_malloc = &Ctx.Idents.get("malloc");
+ if (!II_free)
+ II_free = &Ctx.Idents.get("free");
+
+ if (FD->getIdentifier() == II_malloc) {
+ MallocMem(C, CE);
+ return;
+ }
+
+ if (FD->getIdentifier() == II_free) {
+ FreeMem(C, CE);
+ return;
+ }
+}
+
+void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ SVal CallVal = state->getSVal(CE);
+ SymbolRef Sym = CallVal.getAsLocSymbol();
+ assert(Sym);
+ // Set the symbol's state to Allocated.
+ const GRState *AllocState
+ = state->set<RegionState>(Sym, RefState::getAllocated(CE));
+ C.addTransition(C.GenerateNode(CE, AllocState));
+}
+
+void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ SVal ArgVal = state->getSVal(CE->getArg(0));
+ SymbolRef Sym = ArgVal.getAsLocSymbol();
+ assert(Sym);
+
+ const RefState *RS = state->get<RegionState>(Sym);
+ assert(RS);
+
+ // Check double free.
+ if (RS->isReleased()) {
+ ExplodedNode *N = C.GenerateNode(CE, true);
+ if (N) {
+ if (!BT_DoubleFree)
+ BT_DoubleFree = new BuiltinBug("Double free",
+ "Try to free a memory block that has been released");
+ // FIXME: should find where it's freed last time.
+ BugReport *R = new BugReport(*BT_DoubleFree,
+ BT_DoubleFree->getDescription(), N);
+ C.EmitReport(R);
+ }
+ return;
+ }
+
+ // Normal free.
+ const GRState *FreedState
+ = state->set<RegionState>(Sym, RefState::getReleased(CE));
+ C.addTransition(C.GenerateNode(CE, FreedState));
+}
+
+void MallocChecker::EvalDeadSymbols(CheckerContext &C, const Stmt *S,
+ SymbolReaper &SymReaper) {
+ for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+ E = SymReaper.dead_end(); I != E; ++I) {
+ SymbolRef Sym = *I;
+ const GRState *state = C.getState();
+ const RefState *RS = state->get<RegionState>(Sym);
+ if (!RS)
+ return;
+
+ if (RS->isAllocated()) {
+ ExplodedNode *N = C.GenerateNode(S, true);
+ if (N) {
+ if (!BT_Leak)
+ BT_Leak = new BuiltinBug("Memory leak",
+ "Allocated memory never released. Potential memory leak.");
+ // FIXME: where it is allocated.
+ BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+ C.EmitReport(R);
+ }
+ }
+ }
+}
+
+void MallocChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
+ GRExprEngine &Eng) {
+ const GRState *state = B.getState();
+ typedef llvm::ImmutableMap<SymbolRef, RefState> SymMap;
+ SymMap M = state->get<RegionState>();
+
+ for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ RefState RS = I->second;
+ if (RS.isAllocated()) {
+ ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ if (N) {
+ if (!BT_Leak)
+ BT_Leak = new BuiltinBug("Memory leak",
+ "Allocated memory never released. Potential memory leak.");
+ BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+ Eng.getBugReporter().EmitReport(R);
+ }
+ }
+ }
+}
+
+void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
+ const Expr *RetE = S->getRetValue();
+ if (!RetE)
+ return;
+
+ const GRState *state = C.getState();
+
+ SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
+
+ if (!Sym)
+ return;
+
+ const RefState *RS = state->get<RegionState>(Sym);
+ if (!RS)
+ return;
+
+ // FIXME: check other cases.
+ if (RS->isAllocated())
+ state = state->set<RegionState>(Sym, RefState::getEscaped(S));
+
+ ExplodedNode *N = C.GenerateNode(S, state);
+ if (N)
+ C.addTransition(N);
+}
diff --git a/lib/Frontend/ManagerRegistry.cpp b/lib/Analysis/ManagerRegistry.cpp
index 79f1e8178e10..8943db2a2343 100644
--- a/lib/Frontend/ManagerRegistry.cpp
+++ b/lib/Analysis/ManagerRegistry.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/ManagerRegistry.h"
+#include "clang/Analysis/ManagerRegistry.h"
using namespace clang;
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 353e63240294..8c0b85c0c729 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -378,11 +378,29 @@ bool MemRegion::hasGlobalsOrParametersStorage() const {
return false;
}
+// getBaseRegion strips away all elements and fields, and get the base region
+// of them.
+const MemRegion *MemRegion::getBaseRegion() const {
+ const MemRegion *R = this;
+ while (true) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ R = ER->getSuperRegion();
+ continue;
+ }
+ if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
+ R = FR->getSuperRegion();
+ continue;
+ }
+ break;
+ }
+ return R;
+}
+
//===----------------------------------------------------------------------===//
// View handling.
//===----------------------------------------------------------------------===//
-const MemRegion *MemRegion::getBaseRegion() const {
+const MemRegion *MemRegion::StripCasts() const {
const MemRegion *R = this;
while (true) {
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
diff --git a/lib/Analysis/NSErrorChecker.cpp b/lib/Analysis/NSErrorChecker.cpp
index 307686ff57b3..93b617b115d9 100644
--- a/lib/Analysis/NSErrorChecker.cpp
+++ b/lib/Analysis/NSErrorChecker.cpp
@@ -209,15 +209,12 @@ void NSErrorChecker::CheckParamDeref(const VarDecl *Param,
return;
// Iterate over the implicit-null dereferences.
- NullDerefChecker *Checker = Eng.getChecker<NullDerefChecker>();
- assert(Checker && "NullDerefChecker not exist.");
- for (NullDerefChecker::iterator I = Checker->implicit_nodes_begin(),
- E = Checker->implicit_nodes_end(); I != E; ++I) {
-
+ ExplodedNode *const* I, *const* E;
+ llvm::tie(I, E) = GetImplicitNullDereferences(Eng);
+ for ( ; I != E; ++I) {
const GRState *state = (*I)->getState();
- const SVal* X = state->get<GRState::NullDerefTag>();
-
- if (!X || X->getAsSymbol() != ParamSym)
+ SVal location = state->getSVal((*I)->getLocationAs<StmtPoint>()->getStmt());
+ if (location.getAsSymbol() != ParamSym)
continue;
// Emit an error.
diff --git a/lib/Analysis/PointerArithChecker.cpp b/lib/Analysis/PointerArithChecker.cpp
new file mode 100644
index 000000000000..93823484e1d0
--- /dev/null
+++ b/lib/Analysis/PointerArithChecker.cpp
@@ -0,0 +1,71 @@
+//=== PointerArithChecker.cpp - Pointer arithmetic checker -----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines PointerArithChecker, a builtin checker that checks for
+// pointer arithmetic on locations other than array elements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN PointerArithChecker
+ : public CheckerVisitor<PointerArithChecker> {
+ BuiltinBug *BT;
+public:
+ PointerArithChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+}
+
+void *PointerArithChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ if (B->getOpcode() != BinaryOperator::Sub &&
+ B->getOpcode() != BinaryOperator::Add)
+ return;
+
+ const GRState *state = C.getState();
+ SVal LV = state->getSVal(B->getLHS());
+ SVal RV = state->getSVal(B->getRHS());
+
+ const MemRegion *LR = LV.getAsRegion();
+
+ if (!LR || !RV.isConstant())
+ return;
+
+ // If pointer arithmetic is done on variables of non-array type, this often
+ // means behavior rely on memory organization, which is dangerous.
+ if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
+ isa<CompoundLiteralRegion>(LR)) {
+
+ if (ExplodedNode *N = C.GenerateNode(B)) {
+ if (!BT)
+ BT = new BuiltinBug("Dangerous pointer arithmetic",
+ "Pointer arithmetic done on non-array variables "
+ "means reliance on memory layout, which is "
+ "dangerous.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
+ R->addRange(B->getSourceRange());
+ C.EmitReport(R);
+ }
+ }
+}
+
+void clang::RegisterPointerArithChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new PointerArithChecker());
+}
diff --git a/lib/Analysis/PointerSubChecker.cpp b/lib/Analysis/PointerSubChecker.cpp
new file mode 100644
index 000000000000..4c7906f4beba
--- /dev/null
+++ b/lib/Analysis/PointerSubChecker.cpp
@@ -0,0 +1,77 @@
+//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines PointerSubChecker, a builtin checker that checks for
+// pointer subtractions on two pointers pointing to different memory chunks.
+// This check corresponds to CWE-469.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN PointerSubChecker
+ : public CheckerVisitor<PointerSubChecker> {
+ BuiltinBug *BT;
+public:
+ PointerSubChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+}
+
+void *PointerSubChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ // When doing pointer subtraction, if the two pointers do not point to the
+ // same memory chunk, emit a warning.
+ if (B->getOpcode() != BinaryOperator::Sub)
+ return;
+
+ const GRState *state = C.getState();
+ SVal LV = state->getSVal(B->getLHS());
+ SVal RV = state->getSVal(B->getRHS());
+
+ const MemRegion *LR = LV.getAsRegion();
+ const MemRegion *RR = RV.getAsRegion();
+
+ if (!(LR && RR))
+ return;
+
+ const MemRegion *BaseLR = LR->getBaseRegion();
+ const MemRegion *BaseRR = RR->getBaseRegion();
+
+ if (BaseLR == BaseRR)
+ return;
+
+ // Allow arithmetic on different symbolic regions.
+ if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
+ return;
+
+ if (ExplodedNode *N = C.GenerateNode(B)) {
+ if (!BT)
+ BT = new BuiltinBug("Pointer subtraction",
+ "Subtraction of two pointers that do not point to "
+ "the same memory chunk may cause incorrect result.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
+ R->addRange(B->getSourceRange());
+ C.EmitReport(R);
+ }
+}
+
+void clang::RegisterPointerSubChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new PointerSubChecker());
+}
diff --git a/lib/Analysis/PthreadLockChecker.cpp b/lib/Analysis/PthreadLockChecker.cpp
new file mode 100644
index 000000000000..66206616b008
--- /dev/null
+++ b/lib/Analysis/PthreadLockChecker.cpp
@@ -0,0 +1,141 @@
+//===--- PthreadLockChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines PthreadLockChecker, a simple lock -> unlock checker. Eventually
+// this shouldn't be registered with GRExprEngineInternalChecks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/GRStateTrait.h"
+#include "GRExprEngineExperimentalChecks.h"
+#include "llvm/ADT/ImmutableSet.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN PthreadLockChecker
+ : public CheckerVisitor<PthreadLockChecker> {
+ BugType *BT;
+public:
+ PthreadLockChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+
+ void AcquireLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock, bool isTryLock);
+
+ void ReleaseLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock);
+
+};
+} // end anonymous namespace
+
+// GDM Entry for tracking lock state.
+namespace { class VISIBILITY_HIDDEN LockSet {}; }
+namespace clang {
+template <> struct GRStateTrait<LockSet> :
+ public GRStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
+ static void* GDMIndex() { return PthreadLockChecker::getTag(); }
+};
+} // end clang namespace
+
+void clang::RegisterPthreadLockChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new PthreadLockChecker());
+}
+
+
+void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ const CodeTextRegion *R =
+ dyn_cast_or_null<CodeTextRegion>(state->getSVal(Callee).getAsRegion());
+
+ if (!R)
+ return;
+
+ llvm::StringRef FName = R->getDecl()->getName();
+
+ if (FName == "pthread_mutex_lock") {
+ if (CE->getNumArgs() != 1)
+ return;
+ AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false);
+ }
+ else if (FName == "pthread_mutex_trylock") {
+ if (CE->getNumArgs() != 1)
+ return;
+ AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true);
+ }
+ else if (FName == "pthread_mutex_unlock") {
+ if (CE->getNumArgs() != 1)
+ return;
+ ReleaseLock(C, CE, state->getSVal(CE->getArg(0)));
+ }
+}
+
+void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock, bool isTryLock) {
+
+ const MemRegion *lockR = lock.getAsRegion();
+ if (!lockR)
+ return;
+
+ const GRState *state = C.getState();
+
+ SVal X = state->getSVal(CE);
+ if (X.isUnknownOrUndef())
+ return;
+
+ DefinedSVal retVal = cast<DefinedSVal>(X);
+ const GRState *lockSucc = state;
+
+ if (isTryLock) {
+ // Bifurcate the state, and allow a mode where the lock acquisition fails.
+ const GRState *lockFail;
+ llvm::tie(lockFail, lockSucc) = state->Assume(retVal);
+ assert(lockFail && lockSucc);
+ C.addTransition(C.GenerateNode(CE, lockFail));
+ }
+ else {
+ // Assume that the return value was 0.
+ lockSucc = state->Assume(retVal, false);
+ assert(lockSucc);
+ }
+
+ // Record that the lock was acquired.
+ lockSucc = lockSucc->add<LockSet>(lockR);
+
+ C.addTransition(lockSucc != state ? C.GenerateNode(CE, lockSucc) :
+ C.getPredecessor());
+}
+
+void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock) {
+
+ const MemRegion *lockR = lock.getAsRegion();
+ if (!lockR)
+ return;
+
+ const GRState *state = C.getState();
+
+ // Record that the lock was released.
+ // FIXME: Handle unlocking locks that were never acquired. This may
+ // require IPA for wrappers.
+ const GRState *unlockState = state->remove<LockSet>(lockR);
+
+ if (state == unlockState)
+ return;
+
+ C.addTransition(C.GenerateNode(CE, unlockState));
+}
diff --git a/lib/Analysis/RangeConstraintManager.cpp b/lib/Analysis/RangeConstraintManager.cpp
index 73b445e6ab36..f5cae698f924 100644
--- a/lib/Analysis/RangeConstraintManager.cpp
+++ b/lib/Analysis/RangeConstraintManager.cpp
@@ -16,7 +16,7 @@
#include "clang/Analysis/PathSensitive/GRState.h"
#include "clang/Analysis/PathSensitive/GRStateTrait.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
-#include "clang/Frontend/ManagerRegistry.h"
+#include "clang/Analysis/ManagerRegistry.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/FoldingSet.h"
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index dbf8c42d273e..ae3fa14c2a26 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -164,7 +164,7 @@ public:
~RegionStoreSubRegionMap() {}
bool iterSubRegions(const MemRegion* Parent, Visitor& V) const {
- Map::iterator I = M.find(Parent);
+ Map::const_iterator I = M.find(Parent);
if (I == M.end())
return true;
@@ -360,7 +360,8 @@ public:
//===------------------------------------------------------------------===//
const GRState *setExtent(const GRState *state, const MemRegion* R, SVal Extent);
- SVal getSizeInElements(const GRState *state, const MemRegion* R);
+ DefinedOrUnknownSVal getSizeInElements(const GRState *state,
+ const MemRegion* R);
//===------------------------------------------------------------------===//
// Utility methods.
@@ -461,7 +462,7 @@ const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,
ASTContext& Ctx = StateMgr.getContext();
// Strip away casts.
- R = R->getBaseRegion();
+ R = R->StripCasts();
// Get the mapping of regions -> subregions.
llvm::OwningPtr<RegionStoreSubRegionMap>
@@ -696,8 +697,8 @@ SVal RegionStoreManager::getLValueElement(QualType elementType, SVal Offset,
// Extents for regions.
//===----------------------------------------------------------------------===//
-SVal RegionStoreManager::getSizeInElements(const GRState *state,
- const MemRegion *R) {
+DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
+ const MemRegion *R) {
switch (R->getKind()) {
case MemRegion::MemSpaceRegionKind:
@@ -1028,16 +1029,20 @@ RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
return SValuator::CastResult(state, UnknownVal());
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
- return CastRetrievedVal(RetrieveField(state, FR), state, FR, T);
+ return SValuator::CastResult(state,
+ CastRetrievedVal(RetrieveField(state, FR), FR, T));
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R))
- return CastRetrievedVal(RetrieveElement(state, ER), state, ER, T);
+ return SValuator::CastResult(state,
+ CastRetrievedVal(RetrieveElement(state, ER), ER, T));
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
- return CastRetrievedVal(RetrieveObjCIvar(state, IVR), state, IVR, T);
+ return SValuator::CastResult(state,
+ CastRetrievedVal(RetrieveObjCIvar(state, IVR), IVR, T));
if (const VarRegion *VR = dyn_cast<VarRegion>(R))
- return CastRetrievedVal(RetrieveVar(state, VR), state, VR, T);
+ return SValuator::CastResult(state,
+ CastRetrievedVal(RetrieveVar(state, VR), VR, T));
RegionBindings B = GetRegionBindings(state->getStore());
RegionBindings::data_type* V = B.lookup(R);
@@ -1109,7 +1114,7 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state,
// FIXME: Handle loads from strings where the literal is treated as
// an integer, e.g., *((unsigned int*)"hello")
ASTContext &Ctx = getContext();
- QualType T = StrR->getValueType(Ctx)->getAs<ArrayType>()->getElementType();
+ QualType T = Ctx.getAsArrayType(StrR->getValueType(Ctx))->getElementType();
if (T != Ctx.getCanonicalType(R->getElementType()))
return UnknownVal();
diff --git a/lib/Analysis/ReturnPointerRangeChecker.cpp b/lib/Analysis/ReturnPointerRangeChecker.cpp
new file mode 100644
index 000000000000..44887b2625da
--- /dev/null
+++ b/lib/Analysis/ReturnPointerRangeChecker.cpp
@@ -0,0 +1,97 @@
+//== ReturnPointerRangeChecker.cpp ------------------------------*- 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 ReturnPointerRangeChecker, which is a path-sensitive check
+// which looks for an out-of-bound pointer being returned to callers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN ReturnPointerRangeChecker :
+ public CheckerVisitor<ReturnPointerRangeChecker> {
+ BuiltinBug *BT;
+public:
+ ReturnPointerRangeChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+};
+}
+
+void clang::RegisterReturnPointerRangeChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new ReturnPointerRangeChecker());
+}
+
+void *ReturnPointerRangeChecker::getTag() {
+ static int x = 0; return &x;
+}
+
+void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *RS) {
+ const GRState *state = C.getState();
+
+ const Expr *RetE = RS->getRetValue();
+ if (!RetE)
+ return;
+
+ SVal V = state->getSVal(RetE);
+ const MemRegion *R = V.getAsRegion();
+ if (!R)
+ return;
+
+ R = R->StripCasts();
+ if (!R)
+ return;
+
+ const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
+ if (!ER)
+ return;
+
+ DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+
+ // FIXME: All of this out-of-bounds checking should eventually be refactored
+ // into a common place.
+
+ DefinedOrUnknownSVal NumElements
+ = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
+
+ const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
+ const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
+ if (StOutBound && !StInBound) {
+ ExplodedNode *N = C.GenerateNode(RS, StOutBound, true);
+
+ if (!N)
+ return;
+
+ // FIXME: This bug correspond to CWE-466. Eventually we should have bug
+ // types explicitly reference such exploit categories (when applicable).
+ if (!BT)
+ BT = new BuiltinBug("Return of pointer value outside of expected range",
+ "Returned pointer value points outside the original object "
+ "(potential buffer overflow)");
+
+ // FIXME: It would be nice to eventually make this diagnostic more clear,
+ // e.g., by referencing the original declaration or by saying *why* this
+ // reference is outside the range.
+
+ // Generate a report for this bug.
+ RangedBugReport *report =
+ new RangedBugReport(*BT, BT->getDescription(), N);
+
+ report->addRange(RetE->getSourceRange());
+
+ C.EmitReport(report);
+ }
+}
diff --git a/lib/Analysis/ReturnStackAddressChecker.cpp b/lib/Analysis/ReturnStackAddressChecker.cpp
new file mode 100644
index 000000000000..e4be8712d09b
--- /dev/null
+++ b/lib/Analysis/ReturnStackAddressChecker.cpp
@@ -0,0 +1,97 @@
+//== ReturnStackAddressChecker.cpp ------------------------------*- 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 ReturnStackAddressChecker, which is a path-sensitive
+// check which looks for the addresses of stack variables being returned to
+// callers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN ReturnStackAddressChecker :
+ public CheckerVisitor<ReturnStackAddressChecker> {
+ BuiltinBug *BT;
+public:
+ ReturnStackAddressChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+};
+}
+
+void clang::RegisterReturnStackAddressChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new ReturnStackAddressChecker());
+}
+
+void *ReturnStackAddressChecker::getTag() {
+ static int x = 0; return &x;
+}
+
+void ReturnStackAddressChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *RS) {
+
+ const Expr *RetE = RS->getRetValue();
+ if (!RetE)
+ return;
+
+ SVal V = C.getState()->getSVal(RetE);
+ const MemRegion *R = V.getAsRegion();
+
+ if (!R || !R->hasStackStorage())
+ return;
+
+ ExplodedNode *N = C.GenerateNode(RS, C.getState(), true);
+
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Return of address to stack-allocated memory");
+
+ // Generate a report for this bug.
+ llvm::SmallString<100> buf;
+ llvm::raw_svector_ostream os(buf);
+ SourceRange range;
+
+ // Check if the region is a compound literal.
+ if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
+ const CompoundLiteralExpr* CL = CR->getLiteralExpr();
+ os << "Address of stack memory associated with a compound literal "
+ "declared on line "
+ << C.getSourceManager().getInstantiationLineNumber(CL->getLocStart())
+ << " returned to caller";
+ range = CL->getSourceRange();
+ }
+ else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
+ const Expr* ARE = AR->getExpr();
+ SourceLocation L = ARE->getLocStart();
+ range = ARE->getSourceRange();
+ os << "Address of stack memory allocated by call to alloca() on line "
+ << C.getSourceManager().getInstantiationLineNumber(L)
+ << " returned to caller";
+ }
+ else {
+ os << "Address of stack memory associated with local variable '"
+ << R->getString() << "' returned.";
+ }
+
+ RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
+ report->addRange(RS->getSourceRange());
+ if (range.isValid())
+ report->addRange(range);
+
+ C.EmitReport(report);
+}
diff --git a/lib/Analysis/ReturnUndefChecker.cpp b/lib/Analysis/ReturnUndefChecker.cpp
new file mode 100644
index 000000000000..796c7608c86d
--- /dev/null
+++ b/lib/Analysis/ReturnUndefChecker.cpp
@@ -0,0 +1,68 @@
+//== ReturnUndefChecker.cpp -------------------------------------*- 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 ReturnUndefChecker, which is a path-sensitive
+// check which looks for undefined or garbage values being returned to the
+// caller.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN ReturnUndefChecker :
+ public CheckerVisitor<ReturnUndefChecker> {
+ BuiltinBug *BT;
+public:
+ ReturnUndefChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+};
+}
+
+void clang::RegisterReturnUndefChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new ReturnUndefChecker());
+}
+
+void *ReturnUndefChecker::getTag() {
+ static int x = 0; return &x;
+}
+
+void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *RS) {
+
+ const Expr *RetE = RS->getRetValue();
+ if (!RetE)
+ return;
+
+ if (!C.getState()->getSVal(RetE).isUndef())
+ return;
+
+ ExplodedNode *N = C.GenerateNode(RS, C.getState(), true);
+
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Garbage return value",
+ "Undefined or garbage value returned to caller");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT, BT->getDescription(), N);
+
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE);
+
+ C.EmitReport(report);
+}
diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp
index 688b7ff6e1e3..d5d36e3b9090 100644
--- a/lib/Analysis/SVals.cpp
+++ b/lib/Analysis/SVals.cpp
@@ -63,7 +63,7 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
SymbolRef SVal::getAsLocSymbol() const {
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
- const MemRegion *R = X->getBaseRegion();
+ const MemRegion *R = X->StripCasts();
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
return SymR->getSymbol();
}
@@ -100,9 +100,9 @@ const MemRegion *SVal::getAsRegion() const {
return 0;
}
-const MemRegion *loc::MemRegionVal::getBaseRegion() const {
+const MemRegion *loc::MemRegionVal::StripCasts() const {
const MemRegion *R = getRegion();
- return R ? R->getBaseRegion() : NULL;
+ return R ? R->StripCasts() : NULL;
}
bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
@@ -173,6 +173,10 @@ nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
// Useful predicates.
//===----------------------------------------------------------------------===//
+bool SVal::isConstant() const {
+ return isa<nonloc::ConcreteInt>(this) || isa<loc::ConcreteInt>(this);
+}
+
bool SVal::isZeroConstant() const {
if (isa<loc::ConcreteInt>(*this))
return cast<loc::ConcreteInt>(*this).getValue() == 0;
diff --git a/lib/Analysis/SValuator.cpp b/lib/Analysis/SValuator.cpp
index 573cac315b3a..ac727b0ac696 100644
--- a/lib/Analysis/SValuator.cpp
+++ b/lib/Analysis/SValuator.cpp
@@ -62,8 +62,7 @@ SValuator::CastResult SValuator::EvalCast(SVal val, const GRState *state,
ASTContext &C = ValMgr.getContext();
// For const casts, just propagate the value.
- if (C.getCanonicalType(castTy).getUnqualifiedType() ==
- C.getCanonicalType(originalTy).getUnqualifiedType())
+ if (C.hasSameUnqualifiedType(castTy, originalTy))
return CastResult(state, val);
// Check for casts from pointers to integers.
diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp
index 4b4ae6580820..2fd72ac0a148 100644
--- a/lib/Analysis/Store.cpp
+++ b/lib/Analysis/Store.cpp
@@ -21,7 +21,7 @@ StoreManager::StoreManager(GRStateManager &stateMgr)
MRMgr(ValMgr.getRegionManager()) {}
const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base,
- QualType EleTy, uint64_t index) {
+ QualType EleTy, uint64_t index) {
SVal idx = ValMgr.makeArrayIndex(index);
return MRMgr.getElementRegion(EleTy, idx, Base, ValMgr.getContext());
}
@@ -43,7 +43,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
// Handle casts to Objective-C objects.
if (CastToTy->isObjCObjectPointerType())
- return R->getBaseRegion();
+ return R->StripCasts();
if (CastToTy->isBlockPointerType()) {
// FIXME: We may need different solutions, depending on the symbol
@@ -64,7 +64,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
// Handle casts to void*. We just pass the region through.
- if (CanonPointeeTy.getUnqualifiedType() == Ctx.VoidTy)
+ if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy)
return R;
// Handle casts from compatible types.
@@ -192,14 +192,14 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
-SValuator::CastResult StoreManager::CastRetrievedVal(SVal V,
- const GRState *state,
- const TypedRegion *R,
- QualType castTy) {
- if (castTy.isNull())
- return SValuator::CastResult(state, V);
-
+SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
+ QualType castTy) {
ASTContext &Ctx = ValMgr.getContext();
- return ValMgr.getSValuator().EvalCast(V, state, castTy, R->getValueType(Ctx));
+
+ if (castTy.isNull())
+ return V;
+
+ assert(Ctx.hasSameUnqualifiedType(castTy, R->getValueType(Ctx)));
+ return V;
}
diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp
index a229f55ff6d9..923a7e1bed0b 100644
--- a/lib/Analysis/UndefinedArgChecker.cpp
+++ b/lib/Analysis/UndefinedArgChecker.cpp
@@ -12,14 +12,28 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "GRExprEngineInternalChecks.h"
using namespace clang;
-void *UndefinedArgChecker::getTag() {
- static int x = 0;
- return &x;
+namespace {
+class VISIBILITY_HIDDEN UndefinedArgChecker
+ : public CheckerVisitor<UndefinedArgChecker> {
+ BugType *BT;
+public:
+ UndefinedArgChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+} // end anonymous namespace
+
+void clang::RegisterUndefinedArgChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new UndefinedArgChecker());
}
void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C,
@@ -29,11 +43,10 @@ void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C,
if (C.getState()->getSVal(*I).isUndef()) {
if (ExplodedNode *N = C.GenerateNode(CE, true)) {
if (!BT)
- BT = new BugType("Pass-by-value argument in function call is "
- "undefined", "Logic error");
+ BT = new BuiltinBug("Pass-by-value argument in function call is "
+ "undefined");
// Generate a report for this bug.
- EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(),
- N);
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
R->addRange((*I)->getSourceRange());
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
C.EmitReport(R);
diff --git a/lib/Analysis/UndefinedArraySubscriptChecker.cpp b/lib/Analysis/UndefinedArraySubscriptChecker.cpp
new file mode 100644
index 000000000000..887c7755fe45
--- /dev/null
+++ b/lib/Analysis/UndefinedArraySubscriptChecker.cpp
@@ -0,0 +1,56 @@
+//===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedArraySubscriptChecker, a builtin check in GRExprEngine
+// that performs checks for undefined array subscripts.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN UndefinedArraySubscriptChecker
+ : public CheckerVisitor<UndefinedArraySubscriptChecker> {
+ BugType *BT;
+public:
+ UndefinedArraySubscriptChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PreVisitArraySubscriptExpr(CheckerContext &C,
+ const ArraySubscriptExpr *A);
+};
+} // end anonymous namespace
+
+void clang::RegisterUndefinedArraySubscriptChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new UndefinedArraySubscriptChecker());
+}
+
+void
+UndefinedArraySubscriptChecker::PreVisitArraySubscriptExpr(CheckerContext &C,
+ const ArraySubscriptExpr *A) {
+ if (C.getState()->getSVal(A->getIdx()).isUndef()) {
+ if (ExplodedNode *N = C.GenerateNode(A, true)) {
+ if (!BT)
+ BT = new BuiltinBug("Array subscript is undefined");
+
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
+ R->addRange(A->getIdx()->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ A->getIdx());
+ C.EmitReport(R);
+ }
+ }
+}
diff --git a/lib/Analysis/UndefinedAssignmentChecker.cpp b/lib/Analysis/UndefinedAssignmentChecker.cpp
index 2e3ac34913ab..b8062f359562 100644
--- a/lib/Analysis/UndefinedAssignmentChecker.cpp
+++ b/lib/Analysis/UndefinedAssignmentChecker.cpp
@@ -36,11 +36,10 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
return;
if (!BT)
- BT = new BugType("Assigned value is garbage or undefined",
- "Logic error");
+ BT = new BuiltinBug("Assigned value is garbage or undefined");
// Generate a report for this bug.
- EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
if (AssignE) {
const Expr *ex = 0;
diff --git a/lib/Analysis/VLASizeChecker.cpp b/lib/Analysis/VLASizeChecker.cpp
index 0e731902f4bb..799a73e293c8 100644
--- a/lib/Analysis/VLASizeChecker.cpp
+++ b/lib/Analysis/VLASizeChecker.cpp
@@ -7,96 +7,91 @@
//
//===----------------------------------------------------------------------===//
//
-// This defines two VLASizeCheckers, a builtin check in GRExprEngine that
+// This defines VLASizeChecker, a builtin check in GRExprEngine that
// performs checks for declaration of VLA of undefined or zero size.
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
using namespace clang;
-void *UndefSizedVLAChecker::getTag() {
- static int x = 0;
- return &x;
+namespace {
+class VISIBILITY_HIDDEN VLASizeChecker : public CheckerVisitor<VLASizeChecker> {
+ BugType *BT_zero;
+ BugType *BT_undef;
+
+public:
+ VLASizeChecker() : BT_zero(0), BT_undef(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
+};
+} // end anonymous namespace
+
+void clang::RegisterVLASizeChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new VLASizeChecker());
}
-ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
- const GRState *state,
- Stmt *S, GRExprEngine &Eng) {
- GRStmtNodeBuilder &Builder = Eng.getBuilder();
- BugReporter &BR = Eng.getBugReporter();
-
- if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
- // FIXME: Handle multi-dimensional VLAs.
- Expr* SE = VLA->getSizeExpr();
- SVal Size_untested = state->getSVal(SE);
-
- if (Size_untested.isUndef()) {
- if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
- N->markAsSink();
- if (!BT)
- BT = new BugType("Declared variable-length array (VLA) uses a garbage"
- " value as its size", "Logic error");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getName().c_str(), N);
- R->addRange(SE->getSourceRange());
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
- BR.EmitReport(R);
- }
- return 0;
- }
+void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
+ if (!DS->isSingleDecl())
+ return;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ if (!VD)
+ return;
+
+ const VariableArrayType *VLA
+ = C.getASTContext().getAsVariableArrayType(VD->getType());
+ if (!VLA)
+ return;
+
+ // FIXME: Handle multi-dimensional VLAs.
+ const Expr* SE = VLA->getSizeExpr();
+ const GRState *state = C.getState();
+ SVal sizeV = state->getSVal(SE);
+
+ if (sizeV.isUndef()) {
+ // Generate an error node.
+ ExplodedNode *N = C.GenerateNode(DS, true);
+ if (!N)
+ return;
+
+ if (!BT_undef)
+ BT_undef = new BuiltinBug("Declared variable-length array (VLA) uses a "
+ "garbage value as its size");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_undef, BT_undef->getName(), N);
+ report->addRange(SE->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ C.EmitReport(report);
+ return;
}
- return Pred;
-}
-
-void *ZeroSizedVLAChecker::getTag() {
- static int x;
- return &x;
-}
-
-ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
- const GRState *state, Stmt *S,
- GRExprEngine &Eng) {
- GRStmtNodeBuilder &Builder = Eng.getBuilder();
- BugReporter &BR = Eng.getBugReporter();
-
- if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
- // FIXME: Handle multi-dimensional VLAs.
- Expr* SE = VLA->getSizeExpr();
- SVal Size_untested = state->getSVal(SE);
-
- DefinedOrUnknownSVal *Size = dyn_cast<DefinedOrUnknownSVal>(&Size_untested);
- // Undefined size is checked in another checker.
- if (!Size)
- return Pred;
-
- const GRState *zeroState = state->Assume(*Size, false);
- state = state->Assume(*Size, true);
-
- if (zeroState && !state) {
- if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
- N->markAsSink();
- if (!BT)
- BT = new BugType("Declared variable-length array (VLA) has zero size",
- "Logic error");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getName().c_str(), N);
- R->addRange(SE->getSourceRange());
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
- BR.EmitReport(R);
- }
- }
- if (!state)
- return 0;
-
- return Builder.generateNode(S, state, Pred);
+
+ // Check if the size is zero.
+ DefinedOrUnknownSVal sizeD = cast<DefinedOrUnknownSVal>(sizeV);
+
+ const GRState *stateNotZero, *stateZero;
+ llvm::tie(stateNotZero, stateZero) = state->Assume(sizeD);
+
+ if (stateZero && !stateNotZero) {
+ ExplodedNode* N = C.GenerateNode(DS, stateZero, true);
+ if (!BT_zero)
+ BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
+ "size");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_zero, BT_zero->getName(), N);
+ report->addRange(SE->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ C.EmitReport(report);
+ return;
}
- else
- return Pred;
+
+ // From this point on, assume that the size is not zero.
+ if (state != stateNotZero)
+ C.addTransition(C.GenerateNode(DS, stateNotZero));
}
-
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 962cb4c42a8a..a85bef0f29ed 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -715,8 +715,8 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc) const {
-static void ComputeLineNumbers(ContentCache* FI,
- llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE;
+static DISABLE_INLINE void ComputeLineNumbers(ContentCache* FI,
+ llvm::BumpPtrAllocator &Alloc);
static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
// Note that calling 'getBuffer()' may lazily page in the file.
const MemoryBuffer *Buffer = FI->getBuffer();
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 12caf0c8e512..b6c4df87f272 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include <cstdlib>
@@ -24,9 +25,6 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
// These should be overridden by concrete targets as needed.
TLSSupported = true;
PointerWidth = PointerAlign = 32;
- WCharWidth = WCharAlign = 32;
- Char16Width = Char16Align = 16;
- Char32Width = Char32Align = 32;
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
LongLongWidth = LongLongAlign = 64;
@@ -36,7 +34,6 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
DoubleAlign = 64;
LongDoubleWidth = 64;
LongDoubleAlign = 64;
- IntMaxTWidth = 64;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntMaxType = SignedLongLong;
@@ -51,7 +48,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
DoubleFormat = &llvm::APFloat::IEEEdouble;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64";
+ "i64:64:64-f32:32:32-f64:64:64-n32";
UserLabelPrefix = "_";
}
@@ -95,17 +92,33 @@ const char *TargetInfo::getTypeConstantSuffix(IntType T) {
unsigned TargetInfo::getTypeWidth(IntType T) const {
switch (T) {
default: assert(0 && "not an integer!");
- case SignedShort: return getShortWidth();
+ case SignedShort:
case UnsignedShort: return getShortWidth();
- case SignedInt: return getIntWidth();
+ case SignedInt:
case UnsignedInt: return getIntWidth();
- case SignedLong: return getLongWidth();
+ case SignedLong:
case UnsignedLong: return getLongWidth();
- case SignedLongLong: return getLongLongWidth();
+ case SignedLongLong:
case UnsignedLongLong: return getLongLongWidth();
};
}
+/// getTypeAlign - Return the alignment (in bits) of the specified integer type
+/// enum. For example, SignedInt -> getIntAlign().
+unsigned TargetInfo::getTypeAlign(IntType T) const {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort:
+ case UnsignedShort: return getShortAlign();
+ case SignedInt:
+ case UnsignedInt: return getIntAlign();
+ case SignedLong:
+ case UnsignedLong: return getLongAlign();
+ case SignedLongLong:
+ case UnsignedLongLong: return getLongLongAlign();
+ };
+}
+
/// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
bool TargetInfo::isTypeSigned(IntType T) const {
@@ -124,6 +137,14 @@ bool TargetInfo::isTypeSigned(IntType T) const {
};
}
+/// setForcedLangOptions - Set forced language options.
+/// Apply changes to the target information with respect to certain
+/// language options which change the target configuration.
+void TargetInfo::setForcedLangOptions(LangOptions &Opts) {
+ if (Opts.ShortWChar) {
+ WCharType = UnsignedShort;
+ }
+}
//===----------------------------------------------------------------------===//
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index f418c5a81c12..07c2bb960bcf 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -12,14 +12,18 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCSectionMachO.h"
using namespace clang;
@@ -151,29 +155,6 @@ static void getDarwinIPhoneOSDefines(std::vector<char> &Defs,
iPhoneOSStr);
}
-/// GetDarwinLanguageOptions - Set the default language options for darwin.
-static void GetDarwinLanguageOptions(LangOptions &Opts,
- const llvm::Triple &Triple) {
- Opts.NeXTRuntime = true;
-
- if (Triple.getOS() != llvm::Triple::Darwin)
- return;
-
- unsigned MajorVersion = Triple.getDarwinMajorNumber();
-
- // Blocks and stack protectors default to on for 10.6 (darwin10) and beyond.
- if (MajorVersion > 9) {
- Opts.Blocks = 1;
- Opts.setStackProtectorMode(LangOptions::SSPOn);
- }
-
- // Non-fragile ABI (in 64-bit mode) default to on for 10.5 (darwin9) and
- // beyond.
- if (MajorVersion >= 9 && Opts.ObjC1 &&
- Triple.getArch() == llvm::Triple::x86_64)
- Opts.ObjCNonFragileABI = 1;
-}
-
namespace {
template<typename Target>
class DarwinTargetInfo : public OSTargetInfo<Target> {
@@ -184,13 +165,6 @@ protected:
getDarwinOSXDefines(Defines, Triple);
}
- /// getDefaultLangOptions - Allow the target to specify default settings for
- /// various language options. These may be overridden by command line
- /// options.
- virtual void getDefaultLangOptions(LangOptions &Opts) {
- TargetInfo::getDefaultLangOptions(Opts);
- GetDarwinLanguageOptions(Opts, TargetInfo::getTriple());
- }
public:
DarwinTargetInfo(const std::string& triple) :
OSTargetInfo<Target>(triple) {
@@ -320,6 +294,25 @@ public:
: OSTargetInfo<Target>(triple) {}
};
+// PSP Target
+template<typename Target>
+class PSPTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ std::vector<char> &Defs) const {
+ // PSP defines; list based on the output of the pspdev gcc toolchain.
+ Define(Defs, "PSP", "1");
+ Define(Defs, "_PSP", "1");
+ Define(Defs, "__psp__", "1");
+ Define(Defs, "__ELF__", "1");
+ }
+public:
+ PSPTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ }
+};
+
// AuroraUX target
template<typename Target>
class AuroraUXTargetInfo : public OSTargetInfo<Target> {
@@ -413,10 +406,6 @@ public:
return true;
}
}
- virtual void getDefaultLangOptions(LangOptions &Opts) {
- TargetInfo::getDefaultLangOptions(Opts);
- Opts.CharIsSigned = false;
- }
virtual const char *getClobbers() const {
return "";
}
@@ -568,7 +557,7 @@ class PPC32TargetInfo : public PPCTargetInfo {
public:
PPC32TargetInfo(const std::string& triple) : PPCTargetInfo(triple) {
DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v128:128:128";
+ "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32";
}
};
} // end anonymous namespace.
@@ -582,7 +571,7 @@ public:
UIntMaxType = UnsignedLong;
Int64Type = SignedLong;
DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v128:128:128";
+ "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64";
}
};
} // end anonymous namespace.
@@ -655,7 +644,7 @@ public:
bool Enabled) const;
virtual void getDefaultFeatures(const std::string &CPU,
llvm::StringMap<bool> &Features) const;
- virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features);
+ virtual void HandleTargetFeatures(const std::vector<std::string> &Features);
};
void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
@@ -772,21 +761,25 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
/// HandleTargetOptions - Perform initialization based on the user
/// configured set of features.
-void X86TargetInfo::HandleTargetFeatures(const llvm::StringMap<bool>&Features) {
- if (Features.lookup("sse42"))
- SSELevel = SSE42;
- else if (Features.lookup("sse41"))
- SSELevel = SSE41;
- else if (Features.lookup("ssse3"))
- SSELevel = SSSE3;
- else if (Features.lookup("sse3"))
- SSELevel = SSE3;
- else if (Features.lookup("sse2"))
- SSELevel = SSE2;
- else if (Features.lookup("sse"))
- SSELevel = SSE1;
- else if (Features.lookup("mmx"))
- SSELevel = MMX;
+void
+X86TargetInfo::HandleTargetFeatures(const std::vector<std::string> &Features) {
+ // Remember the maximum enabled sselevel.
+ for (unsigned i = 0, e = Features.size(); i !=e; ++i) {
+ // Ignore disabled features.
+ if (Features[i][0] == '-')
+ continue;
+
+ assert(Features[i][0] == '+' && "Invalid target feature!");
+ X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Features[i].substr(1))
+ .Case("sse42", SSE42)
+ .Case("sse41", SSE41)
+ .Case("ssse3", SSSE3)
+ .Case("sse2", SSE2)
+ .Case("sse", SSE1)
+ .Case("mmx", MMX)
+ .Default(NoMMXSSE);
+ SSELevel = std::max(SSELevel, Level);
+ }
}
/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines
@@ -902,7 +895,7 @@ public:
LongDoubleAlign = 32;
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:32:32";
+ "a0:0:64-f80:32:32-n8:16:32";
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
IntPtrType = SignedInt;
@@ -943,7 +936,7 @@ public:
IntPtrType = SignedLong;
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:128:128";
+ "a0:0:64-f80:128:128-n8:16:32";
}
};
@@ -957,11 +950,10 @@ public:
: X86_32TargetInfo(triple) {
TLSSupported = false;
WCharType = UnsignedShort;
- WCharWidth = WCharAlign = 16;
DoubleAlign = LongLongAlign = 64;
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:32:32";
+ "a0:0:64-f80:32:32-n8:16:32";
}
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
@@ -977,11 +969,6 @@ public:
namespace {
-/// GetWindowsVisualStudioLanguageOptions - Set the default language options for Windows.
-static void GetWindowsVisualStudioLanguageOptions(LangOptions &Opts) {
- Opts.Microsoft = true;
-}
-
// x86-32 Windows Visual Studio target
class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo {
public:
@@ -996,10 +983,6 @@ public:
// We lost the original triple, so we use the default.
Define(Defines, "_M_IX86", "600");
}
- virtual void getDefaultLangOptions(LangOptions &Opts) {
- WindowsX86_32TargetInfo::getDefaultLangOptions(Opts);
- GetWindowsVisualStudioLanguageOptions(Opts);
- }
};
} // end anonymous namespace
@@ -1028,11 +1011,10 @@ public:
: X86_32TargetInfo(triple) {
TLSSupported = false;
WCharType = UnsignedShort;
- WCharWidth = WCharAlign = 16;
DoubleAlign = LongLongAlign = 64;
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:32:32";
+ "a0:0:64-f80:32:32-n8:16:32";
}
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
@@ -1059,7 +1041,7 @@ public:
DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
- "a0:0:64-s0:64:64-f80:128:128";
+ "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64";
}
virtual const char *getVAListDeclaration() const {
return "typedef struct __va_list_tag {"
@@ -1087,7 +1069,6 @@ public:
: X86_64TargetInfo(triple) {
TLSSupported = false;
WCharType = UnsignedShort;
- WCharWidth = WCharAlign = 16;
LongWidth = LongAlign = 32;
DoubleAlign = LongLongAlign = 64;
}
@@ -1208,11 +1189,11 @@ public:
if (IsThumb) {
DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-"
- "v64:64:64-v128:128:128-a0:0:32");
+ "v64:64:64-v128:128:128-a0:0:32-n32");
} else {
DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-"
- "v64:64:64-v128:128:128-a0:0:64");
+ "v64:64:64-v128:128:128-a0:0:64-n32");
}
}
virtual const char *getABI() const { return ABI.c_str(); }
@@ -1230,11 +1211,11 @@ public:
if (IsThumb) {
DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
"i64:32:32-f32:32:32-f64:32:32-"
- "v64:64:64-v128:128:128-a0:0:32");
+ "v64:64:64-v128:128:128-a0:0:32-n32");
} else {
DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:32:32-f32:32:32-f64:32:32-"
- "v64:64:64-v128:128:128-a0:0:64");
+ "v64:64:64-v128:128:128-a0:0:64-n32");
}
// FIXME: Override "preferred align" for double and long long.
@@ -1391,7 +1372,7 @@ public:
SparcV8TargetInfo(const std::string& triple) : TargetInfo(triple) {
// FIXME: Support Sparc quad-precision long double?
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64";
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32";
}
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
@@ -1502,7 +1483,6 @@ namespace {
TLSSupported = false;
IntWidth = 16;
LongWidth = LongLongWidth = 32;
- IntMaxTWidth = 32;
PointerWidth = 16;
IntAlign = 8;
LongAlign = LongLongAlign = 8;
@@ -1521,7 +1501,7 @@ namespace {
FloatFormat = &llvm::APFloat::IEEEsingle;
DoubleFormat = &llvm::APFloat::IEEEsingle;
LongDoubleFormat = &llvm::APFloat::IEEEsingle;
- DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-f32:32:32";
+ DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-f32:32:32-n8";
}
virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return 16; }
@@ -1570,7 +1550,6 @@ namespace {
TLSSupported = false;
IntWidth = 16;
LongWidth = LongLongWidth = 32;
- IntMaxTWidth = 32;
PointerWidth = 16;
IntAlign = 8;
LongAlign = LongLongAlign = 8;
@@ -1580,7 +1559,7 @@ namespace {
UIntMaxType = UnsignedLong;
IntPtrType = SignedShort;
PtrDiffType = SignedInt;
- DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8";
+ DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-n8:16";
}
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
@@ -1639,7 +1618,8 @@ namespace {
IntWidth = IntAlign = 32;
LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
PointerWidth = PointerAlign = 64;
- DescriptionString = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16";
+ DescriptionString = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16-n32:64";
}
virtual void getTargetDefines(const LangOptions &Opts,
std::vector<char> &Defines) const {
@@ -1653,11 +1633,6 @@ namespace {
NumRecords = 0;
}
- virtual void getDefaultLangOptions(LangOptions &Opts) {
- TargetInfo::getDefaultLangOptions(Opts);
- Opts.CharIsSigned = false;
- }
-
virtual void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const;
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -1702,7 +1677,7 @@ namespace {
DoubleAlign = 32;
LongLongAlign = 32;
LongDoubleAlign = 32;
- DescriptionString = "e-p:32:32-i64:32-f64:32";
+ DescriptionString = "e-p:32:32-i64:32-f64:32-n32";
}
virtual void getTargetDefines(const LangOptions &Opts,
@@ -1783,7 +1758,6 @@ namespace {
TLSSupported = false;
IntWidth = 32;
LongWidth = LongLongWidth = 32;
- IntMaxTWidth = 32;
PointerWidth = 32;
IntAlign = 32;
LongAlign = LongLongAlign = 32;
@@ -1804,7 +1778,7 @@ namespace {
LongDoubleFormat = &llvm::APFloat::IEEEsingle;
DescriptionString = "E-p:32:32:32-a0:32:32"
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64"
- "-f32:32:32-f64:32:64";
+ "-f32:32:32-f64:32:64-n32";
}
virtual void getTargetDefines(const LangOptions &Opts,
@@ -1832,13 +1806,141 @@ namespace {
};
}
+namespace {
+class MipsTargetInfo : public TargetInfo {
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char * const GCCRegNames[];
+public:
+ MipsTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ DefineStd(Defines, "mips", Opts);
+ Define(Defines, "_mips");
+ DefineStd(Defines, "MIPSEB", Opts);
+ Define(Defines, "_MIPSEB");
+ Define(Defines, "__REGISTER_PREFIX__", "");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement!
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef void* __builtin_va_list;";
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ case 'r': // CPU registers.
+ case 'd': // Equivalent to "r" unless generating MIPS16 code.
+ case 'y': // Equivalent to "r", backwards compatibility only.
+ case 'f': // floating-point registers.
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
+ }
+
+ virtual const char *getClobbers() const {
+ // FIXME: Implement!
+ return "";
+ }
+};
+
+const char * const MipsTargetInfo::GCCRegNames[] = {
+ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ "$24", "$25", "$26", "$27", "$28", "$sp", "$fp", "$31",
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
+ "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
+ "$fcc5","$fcc6","$fcc7"
+};
+
+void MipsTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias MipsTargetInfo::GCCRegAliases[] = {
+ { { "at" }, "$1" },
+ { { "v0" }, "$2" },
+ { { "v1" }, "$3" },
+ { { "a0" }, "$4" },
+ { { "a1" }, "$5" },
+ { { "a2" }, "$6" },
+ { { "a3" }, "$7" },
+ { { "t0" }, "$8" },
+ { { "t1" }, "$9" },
+ { { "t2" }, "$10" },
+ { { "t3" }, "$11" },
+ { { "t4" }, "$12" },
+ { { "t5" }, "$13" },
+ { { "t6" }, "$14" },
+ { { "t7" }, "$15" },
+ { { "s0" }, "$16" },
+ { { "s1" }, "$17" },
+ { { "s2" }, "$18" },
+ { { "s3" }, "$19" },
+ { { "s4" }, "$20" },
+ { { "s5" }, "$21" },
+ { { "s6" }, "$22" },
+ { { "s7" }, "$23" },
+ { { "t8" }, "$24" },
+ { { "t9" }, "$25" },
+ { { "k0" }, "$26" },
+ { { "k1" }, "$27" },
+ { { "gp" }, "$28" },
+ { { "sp" }, "$29" },
+ { { "fp" }, "$30" },
+ { { "ra" }, "$31" }
+};
+
+void MipsTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+}
+} // end anonymous namespace.
+
+namespace {
+class MipselTargetInfo : public MipsTargetInfo {
+public:
+ MipselTargetInfo(const std::string& triple) : MipsTargetInfo(triple) {
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const;
+};
+
+void MipselTargetInfo::getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &Defines) const {
+ DefineStd(Defines, "mips", Opts);
+ Define(Defines, "_mips");
+ DefineStd(Defines, "MIPSEL", Opts);
+ Define(Defines, "_MIPSEL");
+ Define(Defines, "__REGISTER_PREFIX__", "");
+}
+} // end anonymous namespace.
+
//===----------------------------------------------------------------------===//
// Driver code
//===----------------------------------------------------------------------===//
-/// CreateTargetInfo - Return the target info object for the specified target
-/// triple.
-TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
+static TargetInfo *AllocateTarget(const std::string &T) {
llvm::Triple Triple(T);
llvm::Triple::OSType os = Triple.getOS();
@@ -1863,6 +1965,20 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
case llvm::Triple::msp430:
return new MSP430TargetInfo(T);
+ case llvm::Triple::mips:
+ if (os == llvm::Triple::Psp)
+ return new PSPTargetInfo<MipsTargetInfo>(T);
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<MipsTargetInfo>(T);
+ return new MipsTargetInfo(T);
+
+ case llvm::Triple::mipsel:
+ if (os == llvm::Triple::Psp)
+ return new PSPTargetInfo<MipselTargetInfo>(T);
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<MipselTargetInfo>(T);
+ return new MipselTargetInfo(T);
+
case llvm::Triple::pic16:
return new PIC16TargetInfo(T);
@@ -1942,3 +2058,53 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
}
}
}
+
+/// CreateTargetInfo - Return the target info object for the specified target
+/// triple.
+TargetInfo *TargetInfo::CreateTargetInfo(Diagnostic &Diags,
+ const TargetOptions &Opts) {
+ llvm::Triple Triple(Opts.Triple);
+
+ // Construct the target
+ llvm::OwningPtr<TargetInfo> Target(AllocateTarget(Triple.str()));
+ if (!Target) {
+ Diags.Report(diag::err_target_unknown_triple) << Triple.str();
+ return 0;
+ }
+
+ // Set the target ABI if specified.
+ if (!Opts.ABI.empty() && !Target->setABI(Opts.ABI)) {
+ Diags.Report(diag::err_target_unknown_abi) << Opts.ABI;
+ return 0;
+ }
+
+ // Compute the default target features, we need the target to handle this
+ // because features may have dependencies on one another.
+ llvm::StringMap<bool> Features;
+ Target->getDefaultFeatures(Opts.CPU, Features);
+
+ // Apply the user specified deltas.
+ for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
+ ie = Opts.Features.end(); it != ie; ++it) {
+ const char *Name = it->c_str();
+
+ // Apply the feature via the target.
+ if ((Name[0] != '-' && Name[0] != '+') ||
+ !Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
+ Diags.Report(diag::err_target_invalid_feature) << Name;
+ return 0;
+ }
+ }
+
+ // Add the features to the compile options.
+ //
+ // FIXME: If we are completely confident that we have the right set, we only
+ // need to pass the minuses.
+ std::vector<std::string> StrFeatures;
+ for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
+ ie = Features.end(); it != ie; ++it)
+ StrFeatures.push_back(std::string(it->second ? "+" : "-") + it->first());
+ Target->HandleTargetFeatures(StrFeatures);
+
+ return Target.take();
+}
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index 30383f6251f6..ba31544384cb 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -26,6 +26,10 @@ const char *getClangSubversionPath() {
if (End)
*End = 0;
+ End = strstr(URL, "/clang/tools/clang");
+ if (End)
+ *End = 0;
+
char *Begin = strstr(URL, "cfe/");
if (Begin) {
Path = Begin + 4;
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 682cf5da1e72..bc9eb67674ff 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -146,7 +146,23 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (0 && CanBlockBeGlobal(Info))
return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
- std::vector<llvm::Constant*> Elts(5);
+ size_t BlockFields = 5;
+
+ bool hasIntrospection = CGM.getContext().getLangOptions().BlockIntrospection;
+
+ if (hasIntrospection) {
+ BlockFields++;
+ }
+ std::vector<llvm::Constant*> Elts(BlockFields);
+
+ if (hasIntrospection) {
+ std::string BlockTypeEncoding;
+ CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+
+ Elts[5] = llvm::ConstantExpr::getBitCast(
+ CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty);
+ }
+
llvm::Constant *C;
llvm::Value *V;
@@ -154,6 +170,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
// C = BuildBlockStructInitlist();
unsigned int flags = BLOCK_HAS_DESCRIPTOR;
+ if (hasIntrospection)
+ flags |= BLOCK_HAS_OBJC_TYPE;
+
// We run this first so that we set BlockHasCopyDispose from the entire
// block literal.
// __invoke
@@ -211,19 +230,21 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
return C;
}
- std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
+ std::vector<const llvm::Type *> Types(BlockFields+subBlockDeclRefDecls.size());
for (int i=0; i<4; ++i)
Types[i] = Elts[i]->getType();
Types[4] = PtrToInt8Ty;
+ if (hasIntrospection)
+ Types[5] = PtrToInt8Ty;
for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) {
const Expr *E = subBlockDeclRefDecls[i];
const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
QualType Ty = E->getType();
if (BDRE && BDRE->isByRef()) {
- Types[i+5] = llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
+ Types[i+BlockFields] = llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
} else
- Types[i+5] = ConvertType(Ty);
+ Types[i+BlockFields] = ConvertType(Ty);
}
llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
@@ -237,6 +258,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
for (unsigned i=0; i<4; ++i)
Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
+ if (hasIntrospection)
+ Builder.CreateStore(Elts[5], Builder.CreateStructGEP(V, 5, "block.tmp"));
for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
{
@@ -252,7 +275,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
VD = BDRE->getDecl();
- llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp");
+ llvm::Value* Addr = Builder.CreateStructGEP(V, i+BlockFields, "tmp");
NoteForHelper[helpersize].index = i+5;
NoteForHelper[helpersize].RequiresCopying
= BlockRequiresCopying(VD->getType());
@@ -291,7 +314,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
RValue r = EmitAnyExpr(E, Addr, false);
if (r.isScalar()) {
llvm::Value *Loc = r.getScalarVal();
- const llvm::Type *Ty = Types[i+5];
+ const llvm::Type *Ty = Types[i+BlockFields];
if (BDRE->isByRef()) {
// E is now the address of the value field, instead, we want the
// address of the actual ByRef struct. We optimize this slightly
@@ -375,8 +398,20 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
// int __reserved;
// void (*__invoke)(void *);
// struct __block_descriptor *__descriptor;
+ // // GNU runtime only:
+ // const char *types;
// };
- GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
+ if (CGM.getContext().getLangOptions().BlockIntrospection)
+ GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
+ PtrToInt8Ty,
+ IntTy,
+ IntTy,
+ PtrToInt8Ty,
+ BlockDescPtrTy,
+ PtrToInt8Ty,
+ NULL);
+ else
+ GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
PtrToInt8Ty,
IntTy,
IntTy,
@@ -571,8 +606,12 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
llvm::GlobalVariable::InternalLinkage,
DescriptorStruct, "__block_descriptor_global");
+ int FieldCount = 5;
// Generate the constants for the block literal.
- llvm::Constant *LiteralFields[5];
+ if (CGM.getContext().getLangOptions().BlockIntrospection)
+ FieldCount = 6;
+
+ std::vector<llvm::Constant*> LiteralFields(FieldCount);
CodeGenFunction::BlockInfo Info(0, n);
uint64_t subBlockSize, subBlockAlign;
@@ -592,7 +631,9 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
LiteralFields[0] = getNSConcreteGlobalBlock();
// Flags
- LiteralFields[1] =
+ LiteralFields[1] = CGM.getContext().getLangOptions().BlockIntrospection ?
+ llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR |
+ BLOCK_HAS_OBJC_TYPE) :
llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR);
// Reserved
@@ -603,9 +644,17 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
// Descriptor
LiteralFields[4] = Descriptor;
+
+ // Type encoding
+ if (CGM.getContext().getLangOptions().BlockIntrospection) {
+ std::string BlockTypeEncoding;
+ CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+
+ LiteralFields[5] = CGM.GetAddrOfConstantCString(BlockTypeEncoding);
+ }
llvm::Constant *BlockLiteralStruct =
- llvm::ConstantStruct::get(VMContext, &LiteralFields[0], 5, false);
+ llvm::ConstantStruct::get(VMContext, LiteralFields, false);
llvm::GlobalVariable *BlockLiteral =
new llvm::GlobalVariable(getModule(), BlockLiteralStruct->getType(), true,
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 3ab4efb71bee..38e02a70a4e2 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -55,7 +55,8 @@ public:
BLOCK_HAS_CXX_OBJ = (1 << 26),
BLOCK_IS_GC = (1 << 27),
BLOCK_IS_GLOBAL = (1 << 28),
- BLOCK_HAS_DESCRIPTOR = (1 << 29)
+ BLOCK_HAS_DESCRIPTOR = (1 << 29),
+ BLOCK_HAS_OBJC_TYPE = (1 << 30)
};
};
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index c26921969a88..399b8733e720 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -121,7 +121,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
const llvm::Type *ResultType = ConvertType(E->getType());
Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
if (Result->getType() != ResultType)
- Result = Builder.CreateIntCast(Result, ResultType, "cast");
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
return RValue::get(Result);
}
case Builtin::BI__builtin_clz:
@@ -135,7 +136,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
const llvm::Type *ResultType = ConvertType(E->getType());
Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
if (Result->getType() != ResultType)
- Result = Builder.CreateIntCast(Result, ResultType, "cast");
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
return RValue::get(Result);
}
case Builtin::BI__builtin_ffs:
@@ -154,7 +156,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero");
Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs");
if (Result->getType() != ResultType)
- Result = Builder.CreateIntCast(Result, ResultType, "cast");
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
return RValue::get(Result);
}
case Builtin::BI__builtin_parity:
@@ -171,7 +174,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1),
"tmp");
if (Result->getType() != ResultType)
- Result = Builder.CreateIntCast(Result, ResultType, "cast");
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
return RValue::get(Result);
}
case Builtin::BI__builtin_popcount:
@@ -185,7 +189,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
const llvm::Type *ResultType = ConvertType(E->getType());
Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
if (Result->getType() != ResultType)
- Result = Builder.CreateIntCast(Result, ResultType, "cast");
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
return RValue::get(Result);
}
case Builtin::BI__builtin_expect:
@@ -199,8 +204,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, ArgValue, "tmp"));
}
case Builtin::BI__builtin_object_size: {
- // FIXME: We're awaiting the llvm intrincis.
-#if 0
+#if 1
// We pass this builtin onto the optimizer so that it can
// figure out the object size in more complex cases.
const llvm::Type *ResType[] = {
@@ -211,8 +215,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
EmitScalarExpr(E->getArg(0)),
EmitScalarExpr(E->getArg(1))));
#else
- // FIXME: Implement. For now we just always fail and pretend we
- // don't know the object size.
+ // FIXME: Remove after testing.
llvm::APSInt TypeArg = E->getArg(1)->EvaluateAsInt(CGM.getContext());
const llvm::Type *ResType = ConvertType(E->getType());
// bool UseSubObject = TypeArg.getZExtValue() & 1;
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index cf172b1a1cb6..8f5cff4efafe 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -27,7 +27,7 @@ using namespace clang;
using namespace CodeGen;
void
-CodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor,
+CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr) {
const llvm::Type *Int8PtrTy =
llvm::Type::getInt8Ty(VMContext)->getPointerTo();
@@ -55,9 +55,6 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor,
llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
"__dso_handle");
-
- llvm::Constant *DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
-
llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
@@ -82,11 +79,29 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
EmitAggExpr(Init, DeclPtr, isVolatile);
-
+ // Avoid generating destructor(s) for initialized objects.
+ if (!isa<CXXConstructExpr>(Init))
+ return;
+ const ConstantArrayType *Array = getContext().getAsConstantArrayType(T);
+ if (Array)
+ T = getContext().getBaseElementType(Array);
+
if (const RecordType *RT = T->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (!RD->hasTrivialDestructor())
- EmitCXXGlobalDtorRegistration(RD->getDestructor(getContext()), DeclPtr);
+ if (!RD->hasTrivialDestructor()) {
+ llvm::Constant *DtorFn;
+ if (Array) {
+ DtorFn = CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(
+ RD->getDestructor(getContext()),
+ Array, DeclPtr);
+ DeclPtr =
+ llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
+ }
+ else
+ DtorFn = CGM.GetAddrOfCXXDestructor(RD->getDestructor(getContext()),
+ Dtor_Complete);
+ EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
+ }
}
}
}
@@ -267,14 +282,20 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
llvm::Value *Callee;
- if (MD->isVirtual() && !ME->hasQualifier() &&
- !canDevirtualizeMemberFunctionCalls(ME->getBase()))
- Callee = BuildVirtualCall(MD, This, Ty);
- else if (const CXXDestructorDecl *Destructor
- = dyn_cast<CXXDestructorDecl>(MD))
- Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty);
- else
+ if (const CXXDestructorDecl *Destructor
+ = dyn_cast<CXXDestructorDecl>(MD)) {
+ if (MD->isVirtual() && !ME->hasQualifier() &&
+ !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
+ Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty);
+ } else {
+ Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty);
+ }
+ } else if (MD->isVirtual() && !ME->hasQualifier() &&
+ !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
+ Callee = BuildVirtualCall(MD, This, Ty);
+ } else {
Callee = CGM.GetAddrOfFunction(MD, Ty);
+ }
return EmitCXXMemberCall(MD, Callee, This,
CE->arg_begin(), CE->arg_end());
@@ -410,10 +431,15 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
const llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
FPT->isVariadic());
- llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, Ty);
llvm::Value *This = EmitLValue(E->getArg(0)).getAddress();
+ llvm::Value *Callee;
+ if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0)))
+ Callee = BuildVirtualCall(MD, This, Ty);
+ else
+ Callee = CGM.GetAddrOfFunction(MD, Ty);
+
return EmitCXXMemberCall(MD, Callee, This,
E->arg_begin() + 1, E->arg_end());
}
@@ -506,16 +532,25 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
llvm::Value *This) {
const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
assert(CA && "Do we support VLA for destruction ?");
+ uint64_t ElementCount = getContext().getConstantArrayElementCount(CA);
+ llvm::Value* ElementCountPtr =
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount);
+ EmitCXXAggrDestructorCall(D, ElementCountPtr, This);
+}
+
+/// EmitCXXAggrDestructorCall - calls the default destructor on array
+/// elements in reverse order of construction.
+void
+CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+ llvm::Value *UpperCount,
+ llvm::Value *This) {
llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
1);
- uint64_t ElementCount = getContext().getConstantArrayElementCount(CA);
// Create a temporary for the loop index and initialize it with count of
// array elements.
llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext),
"loop.index");
// Index = ElementCount;
- llvm::Value* UpperCount =
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount);
Builder.CreateStore(UpperCount, IndexPtr, false);
// Start the loop with a block that tests the condition.
@@ -543,7 +578,16 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
Counter = Builder.CreateLoad(IndexPtr);
Counter = Builder.CreateSub(Counter, One);
llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx");
- EmitCXXDestructorCall(D, Dtor_Complete, Address);
+ if (D->isVirtual()) {
+ const llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(D),
+ /*isVariadic=*/false);
+
+ llvm::Value *Callee = BuildVirtualCall(D, Dtor_Deleting, Address, Ty);
+ EmitCXXMemberCall(D, Callee, Address, 0, 0);
+ }
+ else
+ EmitCXXDestructorCall(D, Dtor_Complete, Address);
EmitBlock(ContinueBlock);
@@ -559,6 +603,50 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
EmitBlock(AfterFor, true);
}
+/// GenerateCXXAggrDestructorHelper - Generates a helper function which when invoked,
+/// calls the default destructor on array elements in reverse order of
+/// construction.
+llvm::Constant *
+CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This) {
+ static int UniqueCount;
+ FunctionArgList Args;
+ ImplicitParamDecl *Dst =
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+ Args.push_back(std::make_pair(Dst, Dst->getType()));
+
+ llvm::SmallString<16> Name;
+ llvm::raw_svector_ostream(Name) << "__tcf_" << (++UniqueCount);
+ QualType R = getContext().VoidTy;
+ const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args);
+ const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
+ llvm::Function *Fn =
+ llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
+ Name.c_str(),
+ &CGM.getModule());
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get(Name.c_str());
+ FunctionDecl *FD = FunctionDecl::Create(getContext(),
+ getContext().getTranslationUnitDecl(),
+ SourceLocation(), II, R, 0,
+ FunctionDecl::Static,
+ false, true);
+ StartFunction(FD, R, Fn, Args, SourceLocation());
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
+ EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
+ FinishFunction();
+ llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),
+ 0);
+ llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
+ return m;
+}
+
void
CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CXXCtorType Type,
@@ -612,8 +700,13 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
// Code gen optimization to eliminate copy constructor and return
// its first argument instead.
if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
- CXXConstructExpr::const_arg_iterator i = E->arg_begin();
- EmitAggExpr((*i), Dest, false);
+ const Expr *Arg = E->getArg(0);
+
+ if (const CXXBindTemporaryExpr *BindExpr =
+ dyn_cast<CXXBindTemporaryExpr>(Arg))
+ Arg = BindExpr->getSubExpr();
+
+ EmitAggExpr(Arg, Dest, false);
return;
}
if (Array) {
@@ -649,8 +742,10 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
llvm::Function *
CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
CXXCtorType Type) {
+ const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
const llvm::FunctionType *FTy =
- getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false);
+ getTypes().GetFunctionType(getTypes().getFunctionInfo(D),
+ FPT->isVariadic());
const char *Name = getMangledCXXCtorName(D, Type);
return cast<llvm::Function>(
@@ -668,6 +763,8 @@ const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
}
void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
+ if (D->isVirtual())
+ EmitCXXDestructor(D, Dtor_Deleting);
EmitCXXDestructor(D, Dtor_Complete);
EmitCXXDestructor(D, Dtor_Base);
}
@@ -919,20 +1016,35 @@ CodeGenFunction::GetVirtualCXXBaseClassOffset(llvm::Value *This,
return VBaseOffset;
}
+static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, int64_t VtableIndex,
+ llvm::Value *This, const llvm::Type *Ty) {
+ Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo();
+
+ llvm::Value *Vtable = CGF.Builder.CreateBitCast(This, Ty);
+ Vtable = CGF.Builder.CreateLoad(Vtable);
+
+ llvm::Value *VFuncPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(Vtable, VtableIndex, "vfn");
+ return CGF.Builder.CreateLoad(VFuncPtr);
+}
+
llvm::Value *
-CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This,
+CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
const llvm::Type *Ty) {
- int64_t Index = CGM.getVtableInfo().getMethodVtableIndex(MD);
+ MD = MD->getCanonicalDecl();
+ int64_t VtableIndex = CGM.getVtableInfo().getMethodVtableIndex(MD);
- Ty = llvm::PointerType::get(Ty, 0);
- Ty = llvm::PointerType::get(Ty, 0);
- Ty = llvm::PointerType::get(Ty, 0);
- llvm::Value *vtbl = Builder.CreateBitCast(This, Ty);
- vtbl = Builder.CreateLoad(vtbl);
- llvm::Value *vfn = Builder.CreateConstInBoundsGEP1_64(vtbl,
- Index, "vfn");
- vfn = Builder.CreateLoad(vfn);
- return vfn;
+ return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
+}
+
+llvm::Value *
+CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
+ llvm::Value *&This, const llvm::Type *Ty) {
+ DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
+ int64_t VtableIndex =
+ CGM.getVtableInfo().getMethodVtableIndex(GlobalDecl(DD, Type));
+
+ return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
}
/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class
@@ -1269,8 +1381,16 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
// Do a built-in assignment of scalar data members.
LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0);
- RValue RVRHS = EmitLoadOfLValue(RHS, FieldType);
- EmitStoreThroughLValue(RVRHS, LHS, FieldType);
+ if (!hasAggregateLLVMType(Field->getType())) {
+ RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType());
+ EmitStoreThroughLValue(RVRHS, LHS, Field->getType());
+ } else if (Field->getType()->isAnyComplexType()) {
+ ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(),
+ RHS.isVolatileQualified());
+ StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified());
+ } else {
+ EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType());
+ }
}
FinishFunction();
}
@@ -1366,12 +1486,122 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
FinishFunction();
}
+static void EmitBaseInitializer(CodeGenFunction &CGF,
+ const CXXRecordDecl *ClassDecl,
+ CXXBaseOrMemberInitializer *BaseInit,
+ CXXCtorType CtorType) {
+ assert(BaseInit->isBaseInitializer() &&
+ "Must have base initializer!");
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+
+ const Type *BaseType = BaseInit->getBaseClass();
+ CXXRecordDecl *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+ llvm::Value *V = CGF.GetAddressCXXOfBaseClass(ThisPtr, ClassDecl,
+ BaseClassDecl,
+ /*NullCheckValue=*/false);
+ CGF.EmitCXXConstructorCall(BaseInit->getConstructor(),
+ CtorType, V,
+ BaseInit->const_arg_begin(),
+ BaseInit->const_arg_end());
+}
+
+static void EmitMemberInitializer(CodeGenFunction &CGF,
+ const CXXRecordDecl *ClassDecl,
+ CXXBaseOrMemberInitializer *MemberInit) {
+ assert(MemberInit->isMemberInitializer() &&
+ "Must have member initializer!");
+
+ // non-static data member initializers.
+ FieldDecl *Field = MemberInit->getMember();
+ QualType FieldType = CGF.getContext().getCanonicalType(Field->getType());
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS;
+ if (FieldType->isReferenceType()) {
+ // FIXME: This is really ugly; should be refactored somehow
+ unsigned idx = CGF.CGM.getTypes().getLLVMFieldNo(Field);
+ llvm::Value *V = CGF.Builder.CreateStructGEP(ThisPtr, idx, "tmp");
+ assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
+ LHS = LValue::MakeAddr(V, CGF.MakeQualifiers(FieldType));
+ } else {
+ LHS = CGF.EmitLValueForField(ThisPtr, Field, ClassDecl->isUnion(), 0);
+ }
+
+ // If we are initializing an anonymous union field, drill down to the field.
+ if (MemberInit->getAnonUnionMember()) {
+ Field = MemberInit->getAnonUnionMember();
+ LHS = CGF.EmitLValueForField(LHS.getAddress(), Field,
+ /*IsUnion=*/true, 0);
+ FieldType = Field->getType();
+ }
+
+ // If the field is an array, branch based on the element type.
+ const ConstantArrayType *Array =
+ CGF.getContext().getAsConstantArrayType(FieldType);
+ if (Array)
+ FieldType = CGF.getContext().getBaseElementType(FieldType);
+
+ // We lose the constructor for anonymous union members, so handle them
+ // explicitly.
+ // FIXME: This is somwhat ugly.
+ if (MemberInit->getAnonUnionMember() && FieldType->getAs<RecordType>()) {
+ if (MemberInit->getNumArgs())
+ CGF.EmitAggExpr(*MemberInit->arg_begin(), LHS.getAddress(),
+ LHS.isVolatileQualified());
+ else
+ CGF.EmitAggregateClear(LHS.getAddress(), Field->getType());
+ return;
+ }
+
+ if (FieldType->getAs<RecordType>()) {
+ assert(MemberInit->getConstructor() &&
+ "EmitCtorPrologue - no constructor to initialize member");
+ if (Array) {
+ const llvm::Type *BasePtr = CGF.ConvertType(FieldType);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+ CGF.EmitCXXAggrConstructorCall(MemberInit->getConstructor(),
+ Array, BaseAddrPtr);
+ }
+ else
+ CGF.EmitCXXConstructorCall(MemberInit->getConstructor(),
+ Ctor_Complete, LHS.getAddress(),
+ MemberInit->const_arg_begin(),
+ MemberInit->const_arg_end());
+ return;
+ }
+
+ assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only");
+ Expr *RhsExpr = *MemberInit->arg_begin();
+ RValue RHS;
+ if (FieldType->isReferenceType()) {
+ RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType,
+ /*IsInitializer=*/true);
+ CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+ } else if (Array) {
+ CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType());
+ } else if (!CGF.hasAggregateLLVMType(RhsExpr->getType())) {
+ RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true));
+ CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+ } else if (RhsExpr->getType()->isAnyComplexType()) {
+ CGF.EmitComplexExprIntoAddr(RhsExpr, LHS.getAddress(),
+ LHS.isVolatileQualified());
+ } else {
+ // Handle member function pointers; other aggregates shouldn't get this far.
+ CGF.EmitAggExpr(RhsExpr, LHS.getAddress(), LHS.isVolatileQualified());
+ }
+}
+
/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
/// FIXME: This needs to take a CXXCtorType.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
CXXCtorType CtorType) {
- const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
+ const CXXRecordDecl *ClassDecl = CD->getParent();
+
// FIXME: Add vbase initialization
llvm::Value *LoadOfThis = 0;
@@ -1379,136 +1609,18 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
E = CD->init_end();
B != E; ++B) {
CXXBaseOrMemberInitializer *Member = (*B);
- if (Member->isBaseInitializer()) {
- LoadOfThis = LoadCXXThis();
- Type *BaseType = Member->getBaseClass();
- CXXRecordDecl *BaseClassDecl =
- cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl,
- BaseClassDecl,
- /*NullCheckValue=*/false);
- EmitCXXConstructorCall(Member->getConstructor(),
- CtorType, V,
- Member->const_arg_begin(),
- Member->const_arg_end());
- } else {
- // non-static data member initilaizers.
- FieldDecl *Field = Member->getMember();
- QualType FieldType = getContext().getCanonicalType((Field)->getType());
- const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(FieldType);
- if (Array)
- FieldType = getContext().getBaseElementType(FieldType);
+
+ assert(LiveTemporaries.empty() &&
+ "Should not have any live temporaries at initializer start!");
- LoadOfThis = LoadCXXThis();
- LValue LHS;
- if (FieldType->isReferenceType()) {
- // FIXME: This is really ugly; should be refactored somehow
- unsigned idx = CGM.getTypes().getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(LoadOfThis, idx, "tmp");
- assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
- LHS = LValue::MakeAddr(V, MakeQualifiers(FieldType));
- } else {
- LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
- }
- if (FieldType->getAs<RecordType>()) {
- if (!Field->isAnonymousStructOrUnion()) {
- assert(Member->getConstructor() &&
- "EmitCtorPrologue - no constructor to initialize member");
- if (Array) {
- const llvm::Type *BasePtr = ConvertType(FieldType);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *BaseAddrPtr =
- Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- EmitCXXAggrConstructorCall(Member->getConstructor(),
- Array, BaseAddrPtr);
- }
- else
- EmitCXXConstructorCall(Member->getConstructor(),
- Ctor_Complete, LHS.getAddress(),
- Member->const_arg_begin(),
- Member->const_arg_end());
- continue;
- }
- else {
- // Initializing an anonymous union data member.
- FieldDecl *anonMember = Member->getAnonUnionMember();
- LHS = EmitLValueForField(LHS.getAddress(), anonMember,
- /*IsUnion=*/true, 0);
- FieldType = anonMember->getType();
- }
- }
+ if (Member->isBaseInitializer())
+ EmitBaseInitializer(*this, ClassDecl, Member, CtorType);
+ else
+ EmitMemberInitializer(*this, ClassDecl, Member);
- assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only");
- Expr *RhsExpr = *Member->arg_begin();
- RValue RHS;
- if (FieldType->isReferenceType())
- RHS = EmitReferenceBindingToExpr(RhsExpr, FieldType,
- /*IsInitializer=*/true);
- else if (FieldType->isMemberFunctionPointerType())
- RHS = RValue::get(CGM.EmitConstantExpr(RhsExpr, FieldType, this));
- else
- RHS = RValue::get(EmitScalarExpr(RhsExpr, true));
- EmitStoreThroughLValue(RHS, LHS, FieldType);
- }
- }
-
- if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) {
- // Nontrivial default constructor with no initializer list. It may still
- // have bases classes and/or contain non-static data members which require
- // construction.
- for (CXXRecordDecl::base_class_const_iterator Base =
- ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
- // FIXME. copy assignment of virtual base NYI
- if (Base->isVirtual())
- continue;
-
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- if (BaseClassDecl->hasTrivialConstructor())
- continue;
- if (CXXConstructorDecl *BaseCX =
- BaseClassDecl->getDefaultConstructor(getContext())) {
- LoadOfThis = LoadCXXThis();
- llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl,
- BaseClassDecl,
- /*NullCheckValue=*/false);
- EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0);
- }
- }
-
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- QualType FieldType = getContext().getCanonicalType((*Field)->getType());
- const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(FieldType);
- if (Array)
- FieldType = getContext().getBaseElementType(FieldType);
- if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion())
- continue;
- const RecordType *ClassRec = FieldType->getAs<RecordType>();
- CXXRecordDecl *MemberClassDecl =
- dyn_cast<CXXRecordDecl>(ClassRec->getDecl());
- if (!MemberClassDecl || MemberClassDecl->hasTrivialConstructor())
- continue;
- if (CXXConstructorDecl *MamberCX =
- MemberClassDecl->getDefaultConstructor(getContext())) {
- LoadOfThis = LoadCXXThis();
- LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
- if (Array) {
- const llvm::Type *BasePtr = ConvertType(FieldType);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *BaseAddrPtr =
- Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- EmitCXXAggrConstructorCall(MamberCX, Array, BaseAddrPtr);
- }
- else
- EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(),
- 0, 0);
- }
- }
+ // Pop any live temporaries that the initializers might have pushed.
+ while (!LiveTemporaries.empty())
+ PopCXXTemporary();
}
// Initialize the vtable pointer
@@ -1520,7 +1632,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0);
VtableField = Builder.CreateBitCast(LoadOfThis, PtrPtr8Ty);
- llvm::Value *vtable = GenerateVtable(ClassDecl);
+ llvm::Value *vtable = CGM.getVtableInfo().getVtable(ClassDecl);
Builder.CreateStore(vtable, VtableField);
}
}
@@ -1531,138 +1643,117 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
/// FIXME: This needs to take a CXXDtorType.
void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
CXXDtorType DtorType) {
- const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext());
- assert(!ClassDecl->getNumVBases() &&
- "FIXME: Destruction of virtual bases not supported");
- (void)ClassDecl; // prevent warning.
-
- for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(),
- *E = DD->destr_end(); B != E; ++B) {
- uintptr_t BaseOrMember = (*B);
- if (DD->isMemberToDestroy(BaseOrMember)) {
- FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember);
- QualType FieldType = getContext().getCanonicalType((FD)->getType());
- const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(FieldType);
- if (Array)
- FieldType = getContext().getBaseElementType(FieldType);
- const RecordType *RT = FieldType->getAs<RecordType>();
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (FieldClassDecl->hasTrivialDestructor())
- continue;
- llvm::Value *LoadOfThis = LoadCXXThis();
- LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0);
- if (Array) {
- const llvm::Type *BasePtr = ConvertType(FieldType);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *BaseAddrPtr =
- Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()),
- Array, BaseAddrPtr);
- }
- else
- EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
- Dtor_Complete, LHS.getAddress());
- } else {
- const RecordType *RT =
- DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs<RecordType>();
- CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (BaseClassDecl->hasTrivialDestructor())
- continue;
- llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(),
- ClassDecl, BaseClassDecl,
- /*NullCheckValue=*/false);
- EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()),
- DtorType, V);
- }
- }
- if (DD->getNumBaseOrMemberDestructions() || DD->isTrivial())
- return;
- // Case of destructor synthesis with fields and base classes
- // which have non-trivial destructors. They must be destructed in
- // reverse order of their construction.
- llvm::SmallVector<FieldDecl *, 16> DestructedFields;
+ assert(!DD->isTrivial() &&
+ "Should not emit dtor epilogue for trivial dtor!");
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- QualType FieldType = getContext().getCanonicalType((*Field)->getType());
- if (getContext().getAsConstantArrayType(FieldType))
- FieldType = getContext().getBaseElementType(FieldType);
- if (const RecordType *RT = FieldType->getAs<RecordType>()) {
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (FieldClassDecl->hasTrivialDestructor())
+ const CXXRecordDecl *ClassDecl = DD->getParent();
+
+ // Collect the fields.
+ llvm::SmallVector<const FieldDecl *, 16> FieldDecls;
+ for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); I != E; ++I) {
+ const FieldDecl *Field = *I;
+
+ QualType FieldType = getContext().getCanonicalType(Field->getType());
+ FieldType = getContext().getBaseElementType(FieldType);
+
+ const RecordType *RT = FieldType->getAs<RecordType>();
+ if (!RT)
+ continue;
+
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (FieldClassDecl->hasTrivialDestructor())
continue;
- DestructedFields.push_back(*Field);
- }
+
+ FieldDecls.push_back(Field);
}
- if (!DestructedFields.empty())
- for (int i = DestructedFields.size() -1; i >= 0; --i) {
- FieldDecl *Field = DestructedFields[i];
- QualType FieldType = Field->getType();
- const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(FieldType);
- if (Array)
- FieldType = getContext().getBaseElementType(FieldType);
- const RecordType *RT = FieldType->getAs<RecordType>();
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- llvm::Value *LoadOfThis = LoadCXXThis();
- LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
- if (Array) {
- const llvm::Type *BasePtr = ConvertType(FieldType);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *BaseAddrPtr =
+
+ // Now destroy the fields.
+ for (size_t i = FieldDecls.size(); i > 0; --i) {
+ const FieldDecl *Field = FieldDecls[i - 1];
+
+ QualType FieldType = Field->getType();
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(FieldType);
+ if (Array)
+ FieldType = getContext().getBaseElementType(FieldType);
+
+ const RecordType *RT = FieldType->getAs<RecordType>();
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+
+ llvm::Value *ThisPtr = LoadCXXThis();
+
+ LValue LHS = EmitLValueForField(ThisPtr, Field,
+ /*isUnion=*/false,
+ // FIXME: Qualifiers?
+ /*CVRQualifiers=*/0);
+ if (Array) {
+ const llvm::Type *BasePtr = ConvertType(FieldType);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()),
- Array, BaseAddrPtr);
- }
- else
- EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
- Dtor_Complete, LHS.getAddress());
- }
+ EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()),
+ Array, BaseAddrPtr);
+ } else
+ EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
+ Dtor_Complete, LHS.getAddress());
+ }
- llvm::SmallVector<CXXRecordDecl*, 4> DestructedBases;
- for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
- // FIXME. copy assignment of virtual base NYI
- if (Base->isVirtual())
+ // Destroy non-virtual bases.
+ for (CXXRecordDecl::reverse_base_class_const_iterator I =
+ ClassDecl->bases_rbegin(), E = ClassDecl->bases_rend(); I != E; ++I) {
+ const CXXBaseSpecifier &Base = *I;
+
+ // Ignore virtual bases.
+ if (Base.isVirtual())
continue;
-
+
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore trivial destructors.
if (BaseClassDecl->hasTrivialDestructor())
continue;
- DestructedBases.push_back(BaseClassDecl);
- }
- if (DestructedBases.empty())
- return;
- for (int i = DestructedBases.size() -1; i >= 0; --i) {
- CXXRecordDecl *BaseClassDecl = DestructedBases[i];
+
llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(),
- ClassDecl,BaseClassDecl,
+ ClassDecl, BaseClassDecl,
/*NullCheckValue=*/false);
EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()),
- Dtor_Complete, V);
+ Dtor_Base, V);
}
+
+ // If we're emitting a base destructor, we don't want to emit calls to the
+ // virtual bases.
+ if (DtorType == Dtor_Base)
+ return;
+
+ // FIXME: Handle virtual bases.
+ for (CXXRecordDecl::reverse_base_class_const_iterator I =
+ ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); I != E; ++I) {
+ assert(false && "FIXME: Handle virtual bases.");
+ }
+
+ // If we have a deleting destructor, emit a call to the delete operator.
+ if (DtorType == Dtor_Deleting)
+ EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(),
+ getContext().getTagDeclType(ClassDecl));
}
void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
llvm::Function *Fn,
const FunctionArgList &Args) {
-
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
- assert(!ClassDecl->hasUserDeclaredDestructor() &&
+ assert(!Dtor->getParent()->hasUserDeclaredDestructor() &&
"SynthesizeDefaultDestructor - destructor has user declaration");
- (void) ClassDecl;
StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args,
SourceLocation());
+
EmitDtorEpilogue(Dtor, DtorType);
FinishFunction();
}
-// FIXME: Move this to CGCXXStmt.cpp
+// FIXME: Move this to CGStmtCXX.cpp
void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
// FIXME: We need to do more here.
EmitStmt(S.getTryBlock());
diff --git a/lib/CodeGen/CGCXXClass.cpp b/lib/CodeGen/CGCXXClass.cpp
index 56a28fc9a007..533aabc8616e 100644
--- a/lib/CodeGen/CGCXXClass.cpp
+++ b/lib/CodeGen/CGCXXClass.cpp
@@ -31,6 +31,9 @@ ComputeNonVirtualBaseClassOffset(ASTContext &Context, CXXBasePaths &Paths,
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
const CXXBaseSpecifier *BS = Element.Base;
+ // FIXME: enable test3 from virt.cc to not abort.
+ if (BS->isVirtual())
+ return 0;
assert(!BS->isVirtual() && "Should not see virtual bases here!");
const CXXRecordDecl *Base =
diff --git a/lib/CodeGen/CGCXXExpr.cpp b/lib/CodeGen/CGCXXExpr.cpp
index 2d62df6c58a4..cd7d21b3b951 100644
--- a/lib/CodeGen/CGCXXExpr.cpp
+++ b/lib/CodeGen/CGCXXExpr.cpp
@@ -218,6 +218,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
if (NullCheckResult) {
Builder.CreateBr(NewEnd);
+ NewNotNull = Builder.GetInsertBlock();
EmitBlock(NewNull);
Builder.CreateBr(NewEnd);
EmitBlock(NewEnd);
@@ -233,12 +234,35 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
return NewPtr;
}
-void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
- if (E->isArrayForm()) {
- ErrorUnsupported(E, "delete[] expression");
- return;
- };
+void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
+ llvm::Value *Ptr,
+ QualType DeleteTy) {
+ const FunctionProtoType *DeleteFTy =
+ DeleteFD->getType()->getAs<FunctionProtoType>();
+
+ CallArgList DeleteArgs;
+
+ QualType ArgTy = DeleteFTy->getArgType(0);
+ llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
+ DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
+
+ if (DeleteFTy->getNumArgs() == 2) {
+ QualType SizeTy = DeleteFTy->getArgType(1);
+ uint64_t SizeVal = getContext().getTypeSize(DeleteTy) / 8;
+ llvm::Constant *Size = llvm::ConstantInt::get(ConvertType(SizeTy),
+ SizeVal);
+ DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy));
+ }
+
+ // Emit the call to delete.
+ EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(),
+ DeleteArgs),
+ CGM.GetAddrOfFunction(DeleteFD),
+ DeleteArgs, DeleteFD);
+}
+void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
+
// Get at the argument before we performed the implicit conversion
// to void*.
const Expr *Arg = E->getArgument();
@@ -264,41 +288,237 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
EmitBlock(DeleteNotNull);
-
+
+ bool ShouldCallDelete = true;
+
// Call the destructor if necessary.
if (const RecordType *RT = DeleteTy->getAs<RecordType>()) {
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
if (!RD->hasTrivialDestructor()) {
const CXXDestructorDecl *Dtor = RD->getDestructor(getContext());
- if (Dtor->isVirtual()) {
+ if (E->isArrayForm()) {
+ QualType SizeTy = getContext().getSizeType();
+ uint64_t CookiePadding = std::max(getContext().getTypeSize(SizeTy),
+ static_cast<uint64_t>(getContext().getTypeAlign(DeleteTy))) / 8;
+ if (CookiePadding) {
+ llvm::Type *Ptr8Ty =
+ llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
+ uint64_t CookieOffset =
+ CookiePadding - getContext().getTypeSize(SizeTy) / 8;
+ llvm::Value *AllocatedObjectPtr =
+ Builder.CreateConstInBoundsGEP1_64(
+ Builder.CreateBitCast(Ptr, Ptr8Ty), -CookiePadding);
+ llvm::Value *NumElementsPtr =
+ Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
+ CookieOffset);
+ NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
+ ConvertType(SizeTy)->getPointerTo());
+
+ llvm::Value *NumElements =
+ Builder.CreateLoad(NumElementsPtr);
+ NumElements =
+ Builder.CreateIntCast(NumElements,
+ llvm::Type::getInt64Ty(VMContext), false,
+ "count.tmp");
+ EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr);
+ Ptr = AllocatedObjectPtr;
+ }
+ }
+ else if (Dtor->isVirtual()) {
const llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor),
/*isVariadic=*/false);
- llvm::Value *Callee = BuildVirtualCall(Dtor, Ptr, Ty);
+ llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0);
+
+ // The dtor took care of deleting the object.
+ ShouldCallDelete = false;
} else
EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr);
}
}
}
- // Call delete.
- FunctionDecl *DeleteFD = E->getOperatorDelete();
- const FunctionProtoType *DeleteFTy =
- DeleteFD->getType()->getAs<FunctionProtoType>();
+ if (ShouldCallDelete)
+ EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy);
- CallArgList DeleteArgs;
+ EmitBlock(DeleteEnd);
+}
- QualType ArgTy = DeleteFTy->getArgType(0);
- llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
- DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
+llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
+ QualType Ty = E->getType();
+ const llvm::Type *LTy = ConvertType(Ty)->getPointerTo();
+ if (E->isTypeOperand()) {
+ Ty = E->getTypeOperand();
+ CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
+ Ty = CanTy.getUnqualifiedType().getNonReferenceType();
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->isPolymorphic())
+ return Builder.CreateBitCast(CGM.GenerateRttiRef(RD), LTy);
+ return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy);
+ }
+ return Builder.CreateBitCast(CGM.GenerateRttiNonClass(Ty), LTy);
+ }
+ Expr *subE = E->getExprOperand();
+ Ty = subE->getType();
+ CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
+ Ty = CanTy.getUnqualifiedType().getNonReferenceType();
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->isPolymorphic()) {
+ // FIXME: if subE is an lvalue do
+ LValue Obj = EmitLValue(subE);
+ llvm::Value *This = Obj.getAddress();
+ LTy = LTy->getPointerTo()->getPointerTo();
+ llvm::Value *V = Builder.CreateBitCast(This, LTy);
+ // We need to do a zero check for *p, unless it has NonNullAttr.
+ // FIXME: PointerType->hasAttr<NonNullAttr>()
+ bool CanBeZero = false;
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens()))
+ if (UO->getOpcode() == UnaryOperator::Deref)
+ CanBeZero = true;
+ if (CanBeZero) {
+ llvm::BasicBlock *NonZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ZeroBlock = createBasicBlock();
+
+ llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
+ Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
+ NonZeroBlock, ZeroBlock);
+ EmitBlock(ZeroBlock);
+ /// Call __cxa_bad_typeid
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
+ const llvm::FunctionType *FTy;
+ FTy = llvm::FunctionType::get(ResultType, false);
+ llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
+ Builder.CreateCall(F)->setDoesNotReturn();
+ Builder.CreateUnreachable();
+ EmitBlock(NonZeroBlock);
+ }
+ V = Builder.CreateLoad(V, "vtable");
+ V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL);
+ V = Builder.CreateLoad(V);
+ return V;
+ }
+ return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy);
+ }
+ return Builder.CreateBitCast(CGM.GenerateRttiNonClass(Ty), LTy);
+}
- // Emit the call to delete.
- EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(),
- DeleteArgs),
- CGM.GetAddrOfFunction(DeleteFD),
- DeleteArgs, DeleteFD);
+llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
+ const CXXDynamicCastExpr *DCE) {
+ QualType CastTy = DCE->getTypeAsWritten();
+ QualType InnerType = CastTy->getPointeeType();
+ QualType ArgTy = DCE->getSubExpr()->getType();
+ const llvm::Type *LArgTy = ConvertType(ArgTy);
+ const llvm::Type *LTy = ConvertType(DCE->getType());
+
+ bool CanBeZero = false;
+ bool ToVoid = false;
+ bool ThrowOnBad = false;
+ if (CastTy->isPointerType()) {
+ // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
+ CanBeZero = true;
+ if (InnerType->isVoidType())
+ ToVoid = true;
+ } else {
+ LTy = LTy->getPointerTo();
+ ThrowOnBad = true;
+ }
- EmitBlock(DeleteEnd);
+ CXXRecordDecl *SrcTy;
+ QualType Ty = ArgTy;
+ if (ArgTy.getTypePtr()->isPointerType()
+ || ArgTy.getTypePtr()->isReferenceType())
+ Ty = Ty.getTypePtr()->getPointeeType();
+ CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
+ Ty = CanTy.getUnqualifiedType();
+ SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
+
+ llvm::BasicBlock *ContBlock = createBasicBlock();
+ llvm::BasicBlock *NullBlock = 0;
+ llvm::BasicBlock *NonZeroBlock = 0;
+ if (CanBeZero) {
+ NonZeroBlock = createBasicBlock();
+ NullBlock = createBasicBlock();
+ llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy);
+ Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
+ NonZeroBlock, NullBlock);
+ EmitBlock(NonZeroBlock);
+ }
+
+ llvm::BasicBlock *BadCastBlock = 0;
+
+ const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType());
+
+ // See if this is a dynamic_cast(void*)
+ if (ToVoid) {
+ llvm::Value *This = V;
+ V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo());
+ V = Builder.CreateLoad(V, "vtable");
+ V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL);
+ V = Builder.CreateLoad(V, "offset to top");
+ This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext));
+ V = Builder.CreateInBoundsGEP(This, V);
+ V = Builder.CreateBitCast(V, LTy);
+ } else {
+ /// Call __dynamic_cast
+ const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *PtrToInt8Ty
+ = llvm::Type::getInt8Ty(VMContext)->getPointerTo();
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(PtrDiffTy);
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ CXXRecordDecl *DstTy;
+ Ty = CastTy.getTypePtr()->getPointeeType();
+ CanTy = CGM.getContext().getCanonicalType(Ty);
+ Ty = CanTy.getUnqualifiedType();
+ DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
+
+ // FIXME: Calculate better hint.
+ llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
+ llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy);
+ llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy);
+ V = Builder.CreateBitCast(V, PtrToInt8Ty);
+ V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
+ V, SrcArg, DstArg, hint);
+ V = Builder.CreateBitCast(V, LTy);
+
+ if (ThrowOnBad) {
+ BadCastBlock = createBasicBlock();
+
+ llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
+ Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
+ ContBlock, BadCastBlock);
+ EmitBlock(BadCastBlock);
+ /// Call __cxa_bad_cast
+ ResultType = llvm::Type::getVoidTy(VMContext);
+ const llvm::FunctionType *FBadTy;
+ FBadTy = llvm::FunctionType::get(ResultType, false);
+ llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
+ Builder.CreateCall(F)->setDoesNotReturn();
+ Builder.CreateUnreachable();
+ }
+ }
+
+ if (CanBeZero) {
+ Builder.CreateBr(ContBlock);
+ EmitBlock(NullBlock);
+ Builder.CreateBr(ContBlock);
+ }
+ EmitBlock(ContBlock);
+ if (CanBeZero) {
+ llvm::PHINode *PHI = Builder.CreatePHI(LTy);
+ PHI->reserveOperandSpace(2);
+ PHI->addIncoming(V, NonZeroBlock);
+ PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
+ V = PHI;
+ }
+
+ return V;
}
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 06cd05cc75a8..d0c7d03f20ef 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -19,7 +19,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/Frontend/CompileOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
#include "llvm/Attributes.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Target/TargetData.h"
@@ -441,18 +441,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
RetAttrs |= llvm::Attribute::NoAlias;
}
- if (CompileOpts.OptimizeSize)
+ if (CodeGenOpts.OptimizeSize)
FuncAttrs |= llvm::Attribute::OptimizeForSize;
- if (CompileOpts.DisableRedZone)
+ if (CodeGenOpts.DisableRedZone)
FuncAttrs |= llvm::Attribute::NoRedZone;
- if (CompileOpts.NoImplicitFloat)
+ if (CodeGenOpts.NoImplicitFloat)
FuncAttrs |= llvm::Attribute::NoImplicitFloat;
- if (Features.getStackProtectorMode() == LangOptions::SSPOn)
- FuncAttrs |= llvm::Attribute::StackProtect;
- else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
- FuncAttrs |= llvm::Attribute::StackProtectReq;
-
QualType RetTy = FI.getReturnType();
unsigned Index = 1;
const ABIArgInfo &RetAI = FI.getReturnInfo();
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 1b01e1537b42..055166721085 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -21,7 +21,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Version.h"
-#include "clang/Frontend/CompileOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
@@ -57,7 +57,7 @@ llvm::DIDescriptor CGDebugInfo::getContext(const VarDecl *Decl,
if (Decl->getDeclContext()->isFunctionOrMethod()) {
// Find the last subprogram in region stack.
for (unsigned RI = RegionStack.size(), RE = 0; RI != RE; --RI) {
- llvm::DIDescriptor R = RegionStack[RI - 1];
+ llvm::DIDescriptor R(RegionStack[RI - 1]);
if (R.isSubprogram())
return R;
}
@@ -136,10 +136,11 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
// Create new compile unit.
- return Unit = DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
- AbsFileName.getDirname(),
- Producer, isMain, isOptimized,
- Flags, RuntimeVers);
+ return Unit = DebugFactory.CreateCompileUnit(LangTag,
+ AbsFileName.getLast().c_str(),
+ AbsFileName.getDirname().c_str(),
+ Producer.c_str(), isMain,
+ isOptimized, Flags, RuntimeVers);
}
/// CreateType - Get the Basic type from the cache or create a new
@@ -178,8 +179,6 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
BT->getName(M->getContext().getLangOptions()),
Unit, 0, Size, Align,
Offset, /*flags*/ 0, Encoding);
-
- TypeCache[QualType(BT, 0).getAsOpaquePtr()] = DbgTy.getNode();
return DbgTy;
}
@@ -198,7 +197,6 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
DebugFactory.CreateBasicType(Unit, "complex",
Unit, 0, Size, Align,
Offset, /*flags*/ 0, Encoding);
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
return DbgTy;
}
@@ -236,38 +234,41 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit U
llvm::DIType DbgTy =
DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
0, 0, 0, 0, 0, FromTy);
- TypeCache[Ty.getAsOpaquePtr()] = DbgTy.getNode();
return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
llvm::DICompileUnit Unit) {
- llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit);
-
- // Bit size, align and offset of the type.
- uint64_t Size = M->getContext().getTypeSize(Ty);
- uint64_t Align = M->getContext().getTypeAlign(Ty);
-
llvm::DIType DbgTy =
- DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
- "", llvm::DICompileUnit(),
- 0, Size, Align, 0, 0, EltTy);
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ Ty->getPointeeType(), Unit);
return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
llvm::DICompileUnit Unit) {
- llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit);
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ Ty->getPointeeType(), Unit);
+}
+
+llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
+ const Type *Ty,
+ QualType PointeeTy,
+ llvm::DICompileUnit Unit) {
+ llvm::DIType EltTy = getOrCreateType(PointeeTy, Unit);
// Bit size, align and offset of the type.
- uint64_t Size = M->getContext().getTypeSize(Ty);
+
+ // Size is always the size of a pointer. We can't use getTypeSize here
+ // because that does not return the correct value for references.
+ uint64_t Size =
+ M->getContext().Target.getPointerWidth(PointeeTy.getAddressSpace());
uint64_t Align = M->getContext().getTypeAlign(Ty);
return
- DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
- "", llvm::DICompileUnit(),
+ DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
0, Size, Align, 0, 0, EltTy);
+
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
@@ -407,7 +408,6 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
// We don't set size information, but do specify where the typedef was
// declared.
- std::string TyName = Ty->getDecl()->getNameAsString();
SourceLocation DefLoc = Ty->getDecl()->getLocation();
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
@@ -417,8 +417,8 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
llvm::DIType DbgTy =
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
- TyName, DefUnit, Line, 0, 0, 0, 0, Src);
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ Ty->getDecl()->getNameAsCString(),
+ DefUnit, Line, 0, 0, 0, 0, Src);
return DbgTy;
}
@@ -446,7 +446,6 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
Unit, "", llvm::DICompileUnit(),
0, 0, 0, 0, 0,
llvm::DIType(), EltTypeArray);
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
return DbgTy;
}
@@ -468,8 +467,6 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
SourceManager &SM = M->getContext().getSourceManager();
// Get overall information about the record type for the debug info.
- std::string Name = Decl->getNameAsString();
-
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
llvm::DICompileUnit DefUnit;
unsigned Line = 0;
@@ -485,13 +482,15 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
// 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, Name, DefUnit, Line, 0, 0, 0, 0,
+ DebugFactory.CreateCompositeType(Tag, Unit, Decl->getNameAsString().data(),
+ DefUnit, Line, 0, 0, 0, 0,
llvm::DIType(), llvm::DIArray());
// If this is just a forward declaration, return it.
if (!Decl->getDefinition(M->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();
@@ -508,10 +507,10 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
FieldDecl *Field = *I;
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- std::string FieldName = Field->getNameAsString();
+ const char *FieldName = Field->getNameAsCString();
// Ignore unnamed fields.
- if (FieldName.empty())
+ if (!FieldName)
continue;
// Get the location for the field.
@@ -559,15 +558,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
uint64_t Align = M->getContext().getTypeAlign(Ty);
llvm::DICompositeType RealDecl =
- DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size,
- Align, 0, 0, llvm::DIType(), Elements);
-
- // Update TypeCache.
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl.getNode();
+ DebugFactory.CreateCompositeType(Tag, Unit, Decl->getNameAsString().data(),
+ DefUnit, Line, Size, Align, 0, 0,
+ llvm::DIType(), Elements);
// Now that we have a real decl for the struct, replace anything using the
// old decl with the new one. This will recursively update the debug info.
- FwdDecl.replaceAllUsesWith(RealDecl);
+ llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
return RealDecl;
}
@@ -581,8 +578,6 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
SourceManager &SM = M->getContext().getSourceManager();
// Get overall information about the record type for the debug info.
- std::string Name = Decl->getNameAsString();
-
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation());
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
@@ -597,7 +592,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// 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, Name, DefUnit, Line, 0, 0, 0, 0,
+ DebugFactory.CreateCompositeType(Tag, Unit, Decl->getNameAsCString(),
+ DefUnit, Line, 0, 0, 0, 0,
llvm::DIType(), llvm::DIArray(),
RuntimeLang);
@@ -605,6 +601,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (Decl->isForwardDecl())
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();
@@ -631,10 +628,10 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
ObjCIvarDecl *Field = *I;
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- std::string FieldName = Field->getNameAsString();
+ const char *FieldName = Field->getNameAsCString();
// Ignore unnamed fields.
- if (FieldName.empty())
+ if (!FieldName)
continue;
// Get the location for the field.
@@ -685,16 +682,13 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
uint64_t Align = M->getContext().getTypeAlign(Ty);
llvm::DICompositeType RealDecl =
- DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size,
- Align, 0, 0, llvm::DIType(), Elements,
- RuntimeLang);
-
- // Update TypeCache.
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl.getNode();
+ DebugFactory.CreateCompositeType(Tag, Unit, Decl->getNameAsCString(), DefUnit,
+ Line, Size, Align, 0, 0, llvm::DIType(),
+ Elements, RuntimeLang);
// Now that we have a real decl for the struct, replace anything using the
// old decl with the new one. This will recursively update the debug info.
- FwdDecl.replaceAllUsesWith(RealDecl);
+ llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
return RealDecl;
}
@@ -709,7 +703,7 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
for (EnumDecl::enumerator_iterator
Enum = Decl->enumerator_begin(), EnumEnd = Decl->enumerator_end();
Enum != EnumEnd; ++Enum) {
- Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(),
+ Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsCString(),
Enum->getInitVal().getZExtValue()));
}
@@ -717,7 +711,6 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
llvm::DIArray EltArray =
DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size());
- std::string EnumName = Decl->getNameAsString();
SourceLocation DefLoc = Decl->getLocation();
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
SourceManager &SM = M->getContext().getSourceManager();
@@ -735,11 +728,9 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
llvm::DIType DbgTy =
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
- Unit, EnumName, DefUnit, Line,
+ Unit, Decl->getNameAsCString(), DefUnit, Line,
Size, Align, 0, 0,
llvm::DIType(), EltArray);
-
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
return DbgTy;
}
@@ -797,11 +788,37 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
0, Size, Align, 0, 0,
getOrCreateType(EltTy, Unit),
SubscriptArray);
-
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
return DbgTy;
}
+llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
+ llvm::DICompileUnit Unit) {
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
+ Ty, Ty->getPointeeType(), Unit);
+}
+
+static QualType CanonicalizeTypeForDebugInfo(QualType T) {
+ switch (T->getTypeClass()) {
+ default:
+ return T;
+ case Type::TemplateSpecialization:
+ return cast<TemplateSpecializationType>(T)->desugar();
+ case Type::TypeOfExpr: {
+ TypeOfExprType *Ty = cast<TypeOfExprType>(T);
+ return CanonicalizeTypeForDebugInfo(Ty->getUnderlyingExpr()->getType());
+ }
+ case Type::TypeOf:
+ return cast<TypeOfType>(T)->getUnderlyingType();
+ case Type::Decltype:
+ return cast<DecltypeType>(T)->getUnderlyingType();
+ case Type::QualifiedName:
+ return cast<QualifiedNameType>(T)->getNamedType();
+ case Type::SubstTemplateTypeParm:
+ return cast<SubstTemplateTypeParmType>(T)->getReplacementType();
+ case Type::Elaborated:
+ return cast<ElaboratedType>(T)->getUnderlyingType();
+ }
+}
/// getOrCreateType - Get the type from the cache or create a new
/// one if necessary.
@@ -810,6 +827,9 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
if (Ty.isNull())
return llvm::DIType();
+ // Canonicalize the type.
+ Ty = CanonicalizeTypeForDebugInfo(Ty);
+
// Check for existing entry.
std::map<void *, llvm::WeakVH>::iterator it =
TypeCache.find(Ty.getAsOpaquePtr());
@@ -821,15 +841,17 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
// Otherwise create the type.
llvm::DIType Res = CreateTypeNode(Ty, Unit);
+
+ // And update the type cache.
+ TypeCache[Ty.getAsOpaquePtr()] = Res.getNode();
return Res;
}
-/// getOrCreateTypeNode - Get the type metadata node from the cache or create a
-/// new one if necessary.
+/// CreateTypeNode - Create a new debug type node.
llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
llvm::DICompileUnit Unit) {
// Handle qualifiers, which recursively handles what they refer to.
- if (Ty.hasQualifiers())
+ if (Ty.hasLocalQualifiers())
return CreateQualifiedType(Ty, Unit);
// Work out details of type.
@@ -841,16 +863,13 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
#include "clang/AST/TypeNodes.def"
assert(false && "Dependent types cannot show up in debug information");
- default:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::Vector:
+ // FIXME: Handle these.
case Type::ExtVector:
+ case Type::Vector:
case Type::FixedWidthInt:
- case Type::MemberPointer:
- case Type::TemplateSpecialization:
- case Type::QualifiedName:
- // Unsupported types
+ return llvm::DIType();
+ default:
+ assert(false && "Unhandled type class!");
return llvm::DIType();
case Type::ObjCObjectPointer:
return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
@@ -868,21 +887,14 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
case Type::FunctionProto:
case Type::FunctionNoProto:
return CreateType(cast<FunctionType>(Ty), Unit);
- case Type::Elaborated:
- return getOrCreateType(cast<ElaboratedType>(Ty)->getUnderlyingType(),
- Unit);
-
case Type::ConstantArray:
case Type::VariableArray:
case Type::IncompleteArray:
return CreateType(cast<ArrayType>(Ty), Unit);
- case Type::TypeOfExpr:
- return getOrCreateType(cast<TypeOfExprType>(Ty)->getUnderlyingExpr()
- ->getType(), Unit);
- case Type::TypeOf:
- return getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(), Unit);
- case Type::Decltype:
- return getOrCreateType(cast<DecltypeType>(Ty)->getUnderlyingType(), Unit);
+
+ case Type::LValueReference:
+ return CreateType(cast<LValueReferenceType>(Ty), Unit);
+
}
}
@@ -909,12 +921,8 @@ void CGDebugInfo::EmitFunctionStart(const char *Name, QualType FnType,
getOrCreateType(FnType, Unit),
Fn->hasInternalLinkage(), true/*definition*/);
-#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
- DebugFactory.InsertSubprogramStart(SP, Builder.GetInsertBlock());
-#endif
-
// Push function on region stack.
- RegionStack.push_back(SP);
+ RegionStack.push_back(SP.getNode());
}
@@ -936,31 +944,23 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) {
llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc);
PresumedLoc PLoc = SM.getPresumedLoc(CurLoc);
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
- llvm::DIDescriptor DR = RegionStack.back();
+ llvm::DIDescriptor DR(RegionStack.back());
llvm::DIScope DS = llvm::DIScope(DR.getNode());
llvm::DILocation DO(NULL);
llvm::DILocation DL =
DebugFactory.CreateLocation(PLoc.getLine(), PLoc.getColumn(),
DS, DO);
Builder.SetCurrentDebugLocation(DL.getNode());
-#else
- DebugFactory.InsertStopPoint(Unit, PLoc.getLine(), PLoc.getColumn(),
- Builder.GetInsertBlock());
-#endif
}
/// EmitRegionStart- Constructs the debug code for entering a declarative
/// region - "llvm.dbg.region.start.".
void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) {
- llvm::DIDescriptor D;
- if (!RegionStack.empty())
- D = RegionStack.back();
- D = DebugFactory.CreateLexicalBlock(D);
- RegionStack.push_back(D);
-#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
- DebugFactory.InsertRegionStart(D, Builder.GetInsertBlock());
-#endif
+ llvm::DIDescriptor D =
+ DebugFactory.CreateLexicalBlock(RegionStack.empty() ?
+ llvm::DIDescriptor() :
+ llvm::DIDescriptor(RegionStack.back()));
+ RegionStack.push_back(D.getNode());
}
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
@@ -971,9 +971,6 @@ void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder) {
// Provide an region stop point.
EmitStopPoint(Fn, Builder);
-#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
- DebugFactory.InsertRegionEnd(RegionStack.back(), Builder.GetInsertBlock());
-#endif
RegionStack.pop_back();
}
@@ -985,8 +982,8 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag,
// Do not emit variable debug information while generating optimized code.
// The llvm optimizer and code generator are not yet ready to support
// optimized code debugging.
- const CompileOptions &CO = M->getCompileOpts();
- if (CO.OptimizationLevel)
+ const CodeGenOptions &CGO = M->getCodeGenOpts();
+ if (CGO.OptimizationLevel)
return;
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
@@ -1105,10 +1102,9 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag,
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
FieldSize = M->getContext().getTypeSize(FType);
FieldAlign = Align*8;
- std::string Name = Decl->getNameAsString();
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
- Name, DefUnit,
+ Decl->getNameAsCString(), DefUnit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
@@ -1128,18 +1124,28 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag,
SourceManager &SM = M->getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
unsigned Line = 0;
- if (!PLoc.isInvalid())
+ unsigned Column = 0;
+ if (!PLoc.isInvalid()) {
Line = PLoc.getLine();
- else
+ Column = PLoc.getColumn();
+ } else {
Unit = llvm::DICompileUnit();
-
+ }
// Create the descriptor for the variable.
llvm::DIVariable D =
- DebugFactory.CreateVariable(Tag, RegionStack.back(),Decl->getNameAsString(),
+ DebugFactory.CreateVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
+ Decl->getNameAsCString(),
Unit, Line, Ty);
// Insert an llvm.dbg.declare into the current block.
- DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ llvm::Instruction *Call =
+ DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+
+ llvm::DIScope DS(RegionStack.back());
+ llvm::DILocation DO(NULL);
+ llvm::DILocation DL =
+ DebugFactory.CreateLocation(Line, Column, DS, DO);
+ Builder.SetDebugLocation(Call, DL.getNode());
}
/// EmitDeclare - Emit local variable declaration debug info.
@@ -1152,8 +1158,8 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag,
// Do not emit variable debug information while generating optimized code.
// The llvm optimizer and code generator are not yet ready to support
// optimized code debugging.
- const CompileOptions &CO = M->getCompileOpts();
- if (CO.OptimizationLevel || Builder.GetInsertBlock() == 0)
+ const CodeGenOptions &CGO = M->getCodeGenOpts();
+ if (CGO.OptimizationLevel || Builder.GetInsertBlock() == 0)
return;
uint64_t XOffset = 0;
@@ -1273,11 +1279,10 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag,
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
FieldSize = M->getContext().getTypeSize(FType);
FieldAlign = Align*8;
- std::string Name = Decl->getNameAsString();
XOffset = FieldOffset;
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
- Name, DefUnit,
+ Decl->getNameAsCString(), DefUnit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
@@ -1330,11 +1335,18 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DebugFactory.CreateComplexVariable(Tag, RegionStack.back(),
- Decl->getNameAsString(), Unit, Line, Ty,
+ DebugFactory.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
+ Decl->getNameAsCString(), Unit, Line, Ty,
addr);
// Insert an llvm.dbg.declare into the current block.
- DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertPoint());
+ llvm::Instruction *Call =
+ DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertPoint());
+
+ llvm::DIScope DS(RegionStack.back());
+ llvm::DILocation DO(NULL);
+ llvm::DILocation DL =
+ DebugFactory.CreateLocation(Line, PLoc.getColumn(), DS, DO);
+ Builder.SetDebugLocation(Call, DL.getNode());
}
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl,
@@ -1362,21 +1374,12 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *Decl) {
- // Do not emit variable debug information while generating optimized code.
- // The llvm optimizer and code generator are not yet ready to support
- // optimized code debugging.
- const CompileOptions &CO = M->getCompileOpts();
- if (CO.OptimizationLevel)
- return;
-
// Create global variable debug descriptor.
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
SourceManager &SM = M->getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
- std::string Name = Var->getName();
-
QualType T = Decl->getType();
if (T->isIncompleteArrayType()) {
@@ -1389,9 +1392,9 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
T = M->getContext().getConstantArrayType(ET, ConstVal,
ArrayType::Normal, 0);
}
-
- DebugFactory.CreateGlobalVariable(getContext(Decl, Unit),
- Name, Name, Name, Unit, LineNo,
+ const char *DeclName = Decl->getNameAsCString();
+ DebugFactory.CreateGlobalVariable(getContext(Decl, Unit), DeclName, DeclName,
+ NULL, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(),
true/*definition*/, Var);
@@ -1406,7 +1409,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
- std::string Name = Decl->getNameAsString();
+ const char *Name = Decl->getNameAsCString();
QualType T = M->getContext().getObjCInterfaceType(Decl);
if (T->isIncompleteArrayType()) {
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 2e44e09d2590..af86e2b263fd 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -56,7 +56,7 @@ class CGDebugInfo {
bool BlockLiteralGenericSet;
llvm::DIType BlockLiteralGeneric;
- std::vector<llvm::DIDescriptor> RegionStack;
+ std::vector<llvm::TrackingVH<llvm::MDNode> > RegionStack;
/// Helper functions for getOrCreateType.
llvm::DIType CreateType(const BuiltinType *Ty, llvm::DICompileUnit U);
@@ -73,7 +73,11 @@ class CGDebugInfo {
llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const EnumType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const ArrayType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreatePointerLikeType(unsigned Tag,
+ const Type *Ty, QualType PointeeTy,
+ llvm::DICompileUnit U);
public:
CGDebugInfo(CodeGenModule *m);
~CGDebugInfo();
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 2021ced31683..1d2040bae203 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -19,7 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/CompileOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Target/TargetData.h"
@@ -320,7 +320,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
// All constant structs and arrays should be global if
// their initializer is constant and if the element type is POD.
- if (CGM.getCompileOpts().MergeAllConstants) {
+ if (CGM.getCodeGenOpts().MergeAllConstants) {
if (Ty.isConstant(getContext())
&& (Ty->isArrayType() || Ty->isRecordType())
&& (D.getInit()
@@ -507,7 +507,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
// Handle CXX destruction of variables.
QualType DtorTy(Ty);
- if (const ArrayType *Array = DtorTy->getAs<ArrayType>())
+ while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))
DtorTy = getContext().getBaseElementType(Array);
if (const RecordType *RT = DtorTy->getAs<RecordType>())
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index d9dd70ac9e49..2a544c560931 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -267,6 +267,12 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
case Expr::CXXExprWithTemporariesClass:
return EmitCXXExprWithTemporariesLValue(cast<CXXExprWithTemporaries>(E));
+ case Expr::CXXZeroInitValueExprClass:
+ return EmitNullInitializationLValue(cast<CXXZeroInitValueExpr>(E));
+ case Expr::CXXDefaultArgExprClass:
+ return EmitLValue(cast<CXXDefaultArgExpr>(E)->getExpr());
+ case Expr::CXXTypeidExprClass:
+ return EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E));
case Expr::ObjCMessageExprClass:
return EmitObjCMessageExprLValue(cast<ObjCMessageExpr>(E));
@@ -303,8 +309,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXConstCastExprClass:
return EmitCastLValue(cast<CastExpr>(E));
- case Expr::CXXZeroInitValueExprClass:
- return EmitNullInitializationLValue(cast<CXXZeroInitValueExpr>(E));
}
}
@@ -813,53 +817,53 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
}
}
+static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
+ const Expr *E, const VarDecl *VD) {
+ assert((VD->hasExternalStorage() || VD->isFileVarDecl()) &&
+ "Var decl must have external storage or be a file var decl!");
+
+ llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
+ if (VD->getType()->isReferenceType())
+ V = CGF.Builder.CreateLoad(V, "tmp");
+ LValue LV = LValue::MakeAddr(V, CGF.MakeQualifiers(E->getType()));
+ setObjCGCLValueClass(CGF.getContext(), E, LV);
+ return LV;
+}
+
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
- const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
-
- if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD) ||
- isa<ImplicitParamDecl>(VD))) {
- LValue LV;
- bool NonGCable = VD->hasLocalStorage() &&
- !VD->hasAttr<BlocksAttr>();
- if (VD->hasExternalStorage()) {
- llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
- if (VD->getType()->isReferenceType())
- V = Builder.CreateLoad(V, "tmp");
- LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- } else {
- llvm::Value *V = LocalDeclMap[VD];
- assert(V && "DeclRefExpr not entered in LocalDeclMap?");
-
- Qualifiers Quals = MakeQualifiers(E->getType());
- // local variables do not get their gc attribute set.
- // local static?
- if (NonGCable) Quals.removeObjCGCAttr();
-
- if (VD->hasAttr<BlocksAttr>()) {
- V = Builder.CreateStructGEP(V, 1, "forwarding");
- V = Builder.CreateLoad(V, false);
- V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD),
- VD->getNameAsString());
- }
- if (VD->getType()->isReferenceType())
- V = Builder.CreateLoad(V, "tmp");
- LV = LValue::MakeAddr(V, Quals);
+ const NamedDecl *ND = E->getDecl();
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+
+ // Check if this is a global variable.
+ if (VD->hasExternalStorage() || VD->isFileVarDecl())
+ return EmitGlobalVarDeclLValue(*this, E, VD);
+
+ bool NonGCable = VD->hasLocalStorage() && !VD->hasAttr<BlocksAttr>();
+
+ llvm::Value *V = LocalDeclMap[VD];
+ assert(V && "DeclRefExpr not entered in LocalDeclMap?");
+
+ Qualifiers Quals = MakeQualifiers(E->getType());
+ // local variables do not get their gc attribute set.
+ // local static?
+ if (NonGCable) Quals.removeObjCGCAttr();
+
+ if (VD->hasAttr<BlocksAttr>()) {
+ V = Builder.CreateStructGEP(V, 1, "forwarding");
+ V = Builder.CreateLoad(V, false);
+ V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD),
+ VD->getNameAsString());
}
- LValue::SetObjCNonGC(LV, NonGCable);
- setObjCGCLValueClass(getContext(), E, LV);
- return LV;
- }
-
- if (VD && VD->isFileVarDecl()) {
- llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
- LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ LValue LV = LValue::MakeAddr(V, Quals);
+ LValue::SetObjCNonGC(LV, NonGCable);
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
llvm::Value* V = CGM.GetAddrOfFunction(FD);
if (!FD->hasPrototype()) {
if (const FunctionProtoType *Proto =
@@ -876,20 +880,15 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
}
- if (const ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(E->getDecl())){
- llvm::Value *V = LocalDeclMap[IPD];
- assert(V && "BlockVarDecl not entered in LocalDeclMap?");
- return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- }
-
if (E->getQualifier()) {
// FIXME: the qualifier check does not seem sufficient here
- return EmitPointerToDataMemberLValue(E);
+ return EmitPointerToDataMemberLValue(cast<FieldDecl>(ND));
}
- assert(0 && "Unimp declref");
- //an invalid LValue, but the assert will
- //ensure that this point is never reached.
+ assert(false && "Unhandled DeclRefExpr");
+
+ // an invalid LValue, but the assert will
+ // ensure that this point is never reached.
return LValue();
}
@@ -924,13 +923,17 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
return LV;
}
case UnaryOperator::Real:
- case UnaryOperator::Imag:
+ case UnaryOperator::Imag: {
LValue LV = EmitLValue(E->getSubExpr());
unsigned Idx = E->getOpcode() == UnaryOperator::Imag;
return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(),
Idx, "idx"),
MakeQualifiers(ExprTy));
}
+ case UnaryOperator::PreInc:
+ case UnaryOperator::PreDec:
+ return EmitUnsupportedLValue(E, "pre-inc/dec expression");
+ }
}
LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
@@ -1151,18 +1154,24 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
BaseQuals = BaseTy.getQualifiers();
}
- FieldDecl *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
- // FIXME: Handle non-field member expressions
- assert(Field && "No code generation for non-field member references");
- LValue MemExpLV = EmitLValueForField(BaseValue, Field, isUnion,
- BaseQuals.getCVRQualifiers());
- LValue::SetObjCNonGC(MemExpLV, isNonGC);
- setObjCGCLValueClass(getContext(), E, MemExpLV);
- return MemExpLV;
+ NamedDecl *ND = E->getMemberDecl();
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
+ LValue LV = EmitLValueForField(BaseValue, Field, isUnion,
+ BaseQuals.getCVRQualifiers());
+ LValue::SetObjCNonGC(LV, isNonGC);
+ setObjCGCLValueClass(getContext(), E, LV);
+ return LV;
+ }
+
+ if (VarDecl *VD = dyn_cast<VarDecl>(ND))
+ return EmitGlobalVarDeclLValue(*this, E, VD);
+
+ assert(false && "Unhandled member declaration!");
+ return LValue();
}
LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue,
- FieldDecl* Field,
+ const FieldDecl* Field,
unsigned CVRQualifiers) {
CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field);
@@ -1187,7 +1196,7 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue,
}
LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
- FieldDecl* Field,
+ const FieldDecl* Field,
bool isUnion,
unsigned CVRQualifiers) {
if (Field->isBitField())
@@ -1281,22 +1290,26 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
}
-/// EmitCastLValue - Casts are never lvalues. If a cast is needed by the code
-/// generator in an lvalue context, then it must mean that we need the address
-/// of an aggregate in order to access one of its fields. This can happen for
-/// all the reasons that casts are permitted with aggregate result, including
-/// noop aggregate casts, and cast from scalar to union.
+/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
+/// If the cast is a dynamic_cast, we can have the usual lvalue result,
+/// otherwise if a cast is needed by the code generator in an lvalue context,
+/// then it must mean that we need the address of an aggregate in order to
+/// access one of its fields. This can happen for all the reasons that casts
+/// are permitted with aggregate result, including noop aggregate casts, and
+/// cast from scalar to union.
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
switch (E->getCastKind()) {
default:
- // If this is an lvalue cast, treat it as a no-op.
- // FIXME: We shouldn't need to check for this explicitly!
- if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
- if (ICE->isLvalueCast())
- return EmitLValue(E->getSubExpr());
-
- assert(0 && "Unhandled cast!");
-
+ return EmitUnsupportedLValue(E, "unexpected cast lvalue");
+
+ case CastExpr::CK_Dynamic: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ llvm::Value *V = LV.getAddress();
+ const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(E);
+ return LValue::MakeAddr(EmitDynamicCast(V, DCE),
+ MakeQualifiers(E->getType()));
+ }
+
case CastExpr::CK_NoOp:
case CastExpr::CK_ConstructorConversion:
case CastExpr::CK_UserDefinedConversion:
@@ -1320,13 +1333,24 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
return LValue::MakeAddr(Base, MakeQualifiers(E->getType()));
}
-
case CastExpr::CK_ToUnion: {
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAnyExpr(E->getSubExpr(), Temp, false);
return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
- }
+ }
+ case CastExpr::CK_BaseToDerived: {
+ return EmitUnsupportedLValue(E, "base-to-derived cast lvalue");
+ }
+ case CastExpr::CK_BitCast: {
+ // This must be a reinterpret_cast (or c-style equivalent).
+ const ExplicitCastExpr *CE = cast<ExplicitCastExpr>(E);
+
+ LValue LV = EmitLValue(E->getSubExpr());
+ llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
+ ConvertType(CE->getTypeAsWritten()));
+ return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ }
}
}
@@ -1449,6 +1473,12 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
}
LValue
+CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
+ llvm::Value *Temp = EmitCXXTypeidExpr(E);
+ return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
+}
+
+LValue
CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
LValue LV = EmitLValue(E->getSubExpr());
PushCXXTemporary(E->getTemporary(), LV.getAddress());
@@ -1526,19 +1556,18 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
}
-LValue CodeGenFunction::EmitPointerToDataMemberLValue(const DeclRefExpr *E) {
- const FieldDecl *Field = cast<FieldDecl>(E->getDecl());
+LValue CodeGenFunction::EmitPointerToDataMemberLValue(const FieldDecl *Field) {
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext());
QualType NNSpecTy =
getContext().getCanonicalType(
getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(ClassDecl)));
NNSpecTy = getContext().getPointerType(NNSpecTy);
llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy));
- LValue MemExpLV = EmitLValueForField(V, const_cast<FieldDecl*>(Field),
- /*isUnion*/false, /*Qualifiers*/0);
+ LValue MemExpLV = EmitLValueForField(V, Field, /*isUnion=*/false,
+ /*Qualifiers=*/0);
const llvm::Type *ResultType = ConvertType(getContext().getPointerDiffType());
V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType, "datamember");
- return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ return LValue::MakeAddr(V, MakeQualifiers(Field->getType()));
}
RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
@@ -1571,16 +1600,14 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
LValue CodeGenFunction::
EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
- llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress();
+ llvm::Value *BaseV;
if (E->getOpcode() == BinaryOperator::PtrMemI)
- BaseV = Builder.CreateLoad(BaseV, "indir.ptr");
+ BaseV = EmitScalarExpr(E->getLHS());
+ else
+ BaseV = EmitLValue(E->getLHS()).getAddress();
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext());
BaseV = Builder.CreateBitCast(BaseV, i8Ty);
- LValue RHSLV = EmitLValue(E->getRHS());
- llvm::Value *OffsetV =
- EmitLoadOfLValue(RHSLV, E->getRHS()->getType()).getScalarVal();
- const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType());
- OffsetV = Builder.CreateBitCast(OffsetV, ResultType);
+ llvm::Value *OffsetV = EmitScalarExpr(E->getRHS());
llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr");
QualType Ty = E->getRHS()->getType();
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 901f867a5913..0e10368ab04e 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -114,6 +114,7 @@ public:
void VisitCXXConstructExpr(const CXXConstructExpr *E);
void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
void VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); }
void VisitVAArgExpr(VAArgExpr *E);
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 9145d92128a1..40b845dba050 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -262,7 +262,7 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
uint64_t NumBytes =
AlignedElementOffsetInBytes - ElementOffsetInBytes;
- const llvm::Type *Ty = llvm::Type::getInt8Ty(CGF->getLLVMContext());
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
if (NumBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumBytes);
@@ -766,27 +766,21 @@ public:
return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}
case Expr::PredefinedExprClass: {
- // __func__/__FUNCTION__ -> "". __PRETTY_FUNCTION__ -> "top level".
- std::string Str;
- if (cast<PredefinedExpr>(E)->getIdentType() ==
- PredefinedExpr::PrettyFunction)
- Str = "top level";
+ unsigned Type = cast<PredefinedExpr>(E)->getIdentType();
+ if (CGF) {
+ LValue Res = CGF->EmitPredefinedFunctionName(Type);
+ return cast<llvm::Constant>(Res.getAddress());
+ } else if (Type == PredefinedExpr::PrettyFunction) {
+ return CGM.GetAddrOfConstantCString("top level", ".tmp");
+ }
- return CGM.GetAddrOfConstantCString(Str, ".tmp");
+ return CGM.GetAddrOfConstantCString("", ".tmp");
}
case Expr::AddrLabelExprClass: {
assert(CGF && "Invalid address of label expression outside function.");
-#ifndef USEINDIRECTBRANCH
- unsigned id =
- CGF->GetIDForAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
- llvm::Constant *C =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), id);
- return llvm::ConstantExpr::getIntToPtr(C, ConvertType(E->getType()));
-#else
llvm::Constant *Ptr =
CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
-#endif
}
case Expr::CallExprClass: {
CallExpr* CE = cast<CallExpr>(E);
@@ -827,9 +821,7 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
else
Success = E->Evaluate(Result, Context);
- if (Success) {
- assert(!Result.HasSideEffects &&
- "Constant expr should not have any side effects!");
+ if (Success && !Result.HasSideEffects) {
switch (Result.Val.getKind()) {
case APValue::Uninitialized:
assert(0 && "Constant expressions should be initialized.");
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 96b58d8995ae..e9bbf35fcd8d 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -135,16 +135,8 @@ public:
}
Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
-#ifndef USEINDIRECTBRANCH
- llvm::Value *V =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()),
- CGF.GetIDForAddrOfLabel(E->getLabel()));
-
- return Builder.CreateIntToPtr(V, ConvertType(E->getType()));
-#else
llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
return Builder.CreateBitCast(V, ConvertType(E->getType()));
-#endif
}
// l-values.
@@ -356,6 +348,9 @@ public:
Value *VisitBinLOr (const BinaryOperator *E);
Value *VisitBinComma (const BinaryOperator *E);
+ Value *VisitBinPtrMemD(const Expr *E) { return EmitLoadOfLValue(E); }
+ Value *VisitBinPtrMemI(const Expr *E) { return EmitLoadOfLValue(E); }
+
// Other Operators.
Value *VisitBlockExpr(const BlockExpr *BE);
Value *VisitConditionalOperator(const ConditionalOperator *CO);
@@ -547,13 +542,6 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
//===----------------------------------------------------------------------===//
Value *ScalarExprEmitter::VisitExpr(Expr *E) {
- if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E))
- if (BExpr->getOpcode() == BinaryOperator::PtrMemD) {
- LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(BExpr);
- Value *InVal = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal();
- return InVal;
- }
-
CGF.ErrorUnsupported(E, "scalar expression");
if (E->getType()->isVoidType())
return 0;
@@ -773,49 +761,20 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {
switch (Kind) {
default:
- // FIXME: Assert here.
- // assert(0 && "Unhandled cast kind!");
+ //return CGF.ErrorUnsupported(E, "type of cast");
break;
+
case CastExpr::CK_Unknown:
- // FIXME: We should really assert here - Unknown casts should never get
- // as far as to codegen.
+ //assert(0 && "Unknown cast kind!");
break;
+
case CastExpr::CK_BitCast: {
Value *Src = Visit(const_cast<Expr*>(E));
return Builder.CreateBitCast(Src, ConvertType(DestTy));
}
- case CastExpr::CK_ArrayToPointerDecay: {
- assert(E->getType()->isArrayType() &&
- "Array to pointer decay must have array source type!");
-
- Value *V = EmitLValue(E).getAddress(); // Bitfields can't be arrays.
+ case CastExpr::CK_NoOp:
+ return Visit(const_cast<Expr*>(E));
- // Note that VLA pointers are always decayed, so we don't need to do
- // anything here.
- if (!E->getType()->isVariableArrayType()) {
- assert(isa<llvm::PointerType>(V->getType()) && "Expected pointer");
- assert(isa<llvm::ArrayType>(cast<llvm::PointerType>(V->getType())
- ->getElementType()) &&
- "Expected pointer to array");
- V = Builder.CreateStructGEP(V, 0, "arraydecay");
- }
-
- // The resultant pointer type can be implicitly casted to other pointer
- // types as well (e.g. void*) and can be implicitly converted to integer.
- const llvm::Type *DestLTy = ConvertType(DestTy);
- if (V->getType() != DestLTy) {
- if (isa<llvm::PointerType>(DestLTy))
- V = Builder.CreateBitCast(V, DestLTy, "ptrconv");
- else {
- assert(isa<llvm::IntegerType>(DestLTy) && "Unknown array decay");
- V = Builder.CreatePtrToInt(V, DestLTy, "ptrconv");
- }
- }
- return V;
- }
- case CastExpr::CK_NullToMemberPointer:
- return CGF.CGM.EmitNullConstant(DestTy);
-
case CastExpr::CK_DerivedToBase: {
const RecordType *DerivedClassTy =
E->getType()->getAs<PointerType>()->getPointeeType()->getAs<RecordType>();
@@ -841,6 +800,33 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {
return CGF.GetAddressCXXOfBaseClass(Src, DerivedClassDecl, BaseClassDecl,
NullCheckValue);
}
+ case CastExpr::CK_ToUnion: {
+ assert(0 && "Should be unreachable!");
+ break;
+ }
+ case CastExpr::CK_ArrayToPointerDecay: {
+ assert(E->getType()->isArrayType() &&
+ "Array to pointer decay must have array source type!");
+
+ Value *V = EmitLValue(E).getAddress(); // Bitfields can't be arrays.
+
+ // Note that VLA pointers are always decayed, so we don't need to do
+ // anything here.
+ if (!E->getType()->isVariableArrayType()) {
+ assert(isa<llvm::PointerType>(V->getType()) && "Expected pointer");
+ assert(isa<llvm::ArrayType>(cast<llvm::PointerType>(V->getType())
+ ->getElementType()) &&
+ "Expected pointer to array");
+ V = Builder.CreateStructGEP(V, 0, "arraydecay");
+ }
+
+ return V;
+ }
+ case CastExpr::CK_FunctionToPointerDecay:
+ return EmitLValue(E).getAddress();
+
+ case CastExpr::CK_NullToMemberPointer:
+ return CGF.CGM.EmitNullConstant(DestTy);
case CastExpr::CK_IntegralToPointer: {
Value *Src = Visit(const_cast<Expr*>(E));
@@ -860,7 +846,40 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {
Value *Src = Visit(const_cast<Expr*>(E));
return Builder.CreatePtrToInt(Src, ConvertType(DestTy));
}
-
+
+ case CastExpr::CK_ToVoid: {
+ CGF.EmitAnyExpr(E, 0, false, true);
+ return 0;
+ }
+
+ case CastExpr::CK_Dynamic: {
+ Value *V = Visit(const_cast<Expr*>(E));
+ const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE);
+ return CGF.EmitDynamicCast(V, DCE);
+ }
+
+ case CastExpr::CK_VectorSplat: {
+ const llvm::Type *DstTy = ConvertType(DestTy);
+ Value *Elt = Visit(const_cast<Expr*>(E));
+
+ // Insert the element in element zero of an undef vector
+ llvm::Value *UnV = llvm::UndefValue::get(DstTy);
+ llvm::Value *Idx =
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0);
+ UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp");
+
+ // Splat the element across to all elements
+ llvm::SmallVector<llvm::Constant*, 16> Args;
+ unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
+ for (unsigned i = 0; i < NumElements; i++)
+ Args.push_back(llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(VMContext), 0));
+
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements);
+ llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
+ return Yay;
+ }
+
}
// Handle cases where the source is an non-complex type.
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index f348bfffcb86..b431daa958f0 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -608,6 +608,8 @@ llvm::Constant *CGObjCGNU::GenerateIvarList(
const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
+ if (IvarNames.size() == 0)
+ return NULLPtr;
// Get the method structure type.
llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext,
PtrToInt8Ty,
@@ -1189,8 +1191,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
Context.getObjCEncodingForType((*iter)->getType(), TypeStr);
IvarTypes.push_back(MakeConstantString(TypeStr));
// Get the offset
- uint64_t Offset = 0;
uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter);
+ uint64_t Offset = BaseOffset;
if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
Offset = BaseOffset - superInstanceSize;
}
@@ -1301,7 +1303,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
}
//Generate metaclass for class methods
llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
- NULLPtr, 0x12L, /*name*/"", 0, Zeros[0], GenerateIvarList(
+ NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr);
// Generate the class structure
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 9b2f4a1faee7..4355e66feecd 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -991,6 +991,9 @@ private:
/// for the given class.
llvm::Value *EmitClassRef(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID);
+
+ /// EmitSuperClassRef - Emits reference to class's main metadata class.
+ llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
@@ -1167,6 +1170,9 @@ private:
/// legacy messaging dispatch.
llvm::DenseSet<Selector> NonLegacyDispatchMethods;
+ /// DefinedMetaClasses - List of defined meta-classes.
+ std::vector<llvm::GlobalValue*> DefinedMetaClasses;
+
/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
/// NonLegacyDispatchMethods; false otherwise.
bool LegacyDispatchedSelector(Selector Sel);
@@ -1485,8 +1491,13 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
Target = Super;
}
- } else {
+ }
+ else if (isCategoryImpl)
Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
+ else {
+ llvm::Value *ClassPtr = EmitSuperClassRef(Class);
+ ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
+ Target = CGF.Builder.CreateLoad(ClassPtr);
}
// FIXME: We shouldn't need to do this cast, rectify the ASTContext and
// ObjCTypes types.
@@ -2051,11 +2062,22 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Values[11] = EmitClassExtension(ID);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Values);
-
- llvm::GlobalVariable *GV =
- CreateMetadataVar("\01L_OBJC_CLASS_" + ClassName, Init,
- "__OBJC,__class,regular,no_dead_strip",
- 4, true);
+ std::string Name("\01L_OBJC_CLASS_");
+ Name += ClassName;
+ const char *Section = "__OBJC,__class,regular,no_dead_strip";
+ // Check for a forward reference.
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward metaclass reference has incorrect type.");
+ GV->setLinkage(llvm::GlobalValue::InternalLinkage);
+ GV->setInitializer(Init);
+ GV->setSection(Section);
+ GV->setAlignment(4);
+ CGM.AddUsedGlobal(GV);
+ }
+ else
+ GV = CreateMetadataVar(Name, Init, Section, 4, true);
DefinedClasses.push_back(GV);
}
@@ -2154,6 +2176,22 @@ llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
}
}
+llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
+ std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
+
+ if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
+ true)) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward class metadata reference has incorrect type.");
+ return GV;
+ } else {
+ return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ Name);
+ }
+}
+
/*
struct objc_class_ext {
uint32_t size;
@@ -4095,6 +4133,25 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
AddModuleClassList(DefinedClasses,
"\01L_OBJC_LABEL_CLASS_$",
"__DATA, __objc_classlist, regular, no_dead_strip");
+
+ bool hasWeakImport = false;
+ for (unsigned i = 0; i < DefinedClasses.size(); i++) {
+ llvm::GlobalValue *IMPLGV = DefinedClasses[i];
+ if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
+ continue;
+ IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ hasWeakImport = true;
+ }
+
+ if (hasWeakImport) {
+ for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
+ llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
+ if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
+ continue;
+ IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ }
+ }
+
AddModuleClassList(DefinedNonLazyClasses,
"\01L_OBJC_LABEL_NONLAZY_CLASS_$",
"__DATA, __objc_nlclslist, regular, no_dead_strip");
@@ -4384,6 +4441,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
std::string SuperClassName =
ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString();
SuperClassGV = GetClassGlobal(SuperClassName);
+ if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
+ SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
}
llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
InstanceStart,
@@ -4392,6 +4451,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::GlobalVariable *MetaTClass =
BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
classIsHidden);
+ DefinedMetaClasses.push_back(MetaTClass);
// Metadata for the class
flags = CLS;
@@ -4409,6 +4469,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
std::string RootClassName =
ID->getClassInterface()->getSuperClass()->getNameAsString();
SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
+ if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
+ SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
}
GetClassSizeInfo(ID, InstanceStart, InstanceSize);
CLASS_RO_GV = BuildClassRoTInitializer(flags,
@@ -4489,6 +4551,9 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Values[0] = GetClassName(OCD->getIdentifier());
// meta-class entry symbol
llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
+ if (Interface->hasAttr<WeakImportAttr>())
+ ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+
Values[1] = ClassGV;
std::vector<llvm::Constant*> Methods;
std::string MethodListName(Prefix);
@@ -5178,6 +5243,12 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
/// decl.
llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID) {
+ if (ID->hasAttr<WeakImportAttr>()) {
+ std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
+ llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
+ ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+ }
+
return EmitClassRef(Builder, ID);
}
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 7baf69d87689..8e0864b8dd83 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -208,7 +208,11 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
Align = 1;
}
}
-
+ if (!Align) {
+ assert((D->field_begin() == D->field_end()) && "LayoutUnion - Align 0");
+ Align = 1;
+ }
+
// Append tail padding.
if (Layout.getSize() / 8 > Size)
AppendPadding(Layout.getSize() / 8, Align);
diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp
index 7af15f0a8ca4..e18843d5cf3f 100644
--- a/lib/CodeGen/CGRtti.cpp
+++ b/lib/CodeGen/CGRtti.cpp
@@ -11,36 +11,378 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/Type.h"
+#include "clang/AST/RecordLayout.h"
#include "CodeGenModule.h"
using namespace clang;
using namespace CodeGen;
+class RttiBuilder {
+ CodeGenModule &CGM; // Per-module state.
+ llvm::LLVMContext &VMContext;
+ const llvm::Type *Int8PtrTy;
+ llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
+ llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
+public:
+ RttiBuilder(CodeGenModule &cgm)
+ : CGM(cgm), VMContext(cgm.getModule().getContext()),
+ Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { }
+
+ /// BuildVtableRef - Build a reference to a vtable.
+ llvm::Constant *BuildVtableRef(const char *Name) {
+ // Build a descriptor for Name
+ llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV)
+ GV = llvm::ConstantExpr::getBitCast(GV,
+ llvm::PointerType::get(Int8PtrTy, 0));
+ else {
+ llvm::GlobalVariable::LinkageTypes linktype;
+ linktype = llvm::GlobalValue::ExternalLinkage;
+ GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy,
+ true, linktype, 0, Name);
+ }
+ llvm::Constant *C;
+ C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2);
+ C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1);
+ return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
+ }
+
+ llvm::Constant *BuildName(QualType Ty, bool Hidden) {
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXRttiName(CGM.getMangleContext(), Ty, Out);
+
+ llvm::GlobalVariable::LinkageTypes linktype;
+ linktype = llvm::GlobalValue::LinkOnceODRLinkage;
+
+ llvm::Constant *C;
+ C = llvm::ConstantArray::get(VMContext, Out.str().substr(4));
+
+ llvm::GlobalVariable * GV = new llvm::GlobalVariable(CGM.getModule(),
+ C->getType(),
+ true, linktype, C,
+ Out.str());
+ if (Hidden)
+ GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+ };
+
+ /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info.
+ llvm::Constant *BuildFlags(int f) {
+ return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
+ }
+
+ /// BuildBaseCount - Build a psABI __base_count value for
+ /// __vmi_class_type_info.
+ llvm::Constant *BuildBaseCount(unsigned c) {
+ return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c);
+ }
+
+ llvm::Constant *BuildTypeRef(QualType Ty) {
+ llvm::Constant *C;
+
+ if (!CGM.getContext().getLangOptions().Rtti)
+ return llvm::Constant::getNullValue(Int8PtrTy);
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
+
+ C = CGM.getModule().getGlobalVariable(Out.str());
+ if (C)
+ return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
+
+ llvm::GlobalVariable::LinkageTypes linktype;
+ linktype = llvm::GlobalValue::ExternalLinkage;;
+
+ C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype,
+ 0, Out.str());
+ return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
+ }
+
+ llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) {
+ return BuildTypeRef(CGM.getContext().getTagDeclType(RD));
+ }
+
+ /// CalculateFlags - Calculate the flags for the __vmi_class_type_info
+ /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond
+ /// shaped class.
+ int CalculateFlags(const CXXRecordDecl*RD) {
+ int flags = 0;
+ if (SeenBase.count(RD))
+ flags |= 1;
+ else
+ SeenBase.insert(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()) {
+ if (SeenVBase.count(Base))
+ flags |= 2;
+ else
+ SeenVBase.insert(Base);
+ }
+ flags |= CalculateFlags(Base);
+ }
+ return flags;
+ }
+
+ bool SimpleInheritance(const CXXRecordDecl *RD) {
+ if (RD->getNumBases() != 1)
+ return false;
+ CXXRecordDecl::base_class_const_iterator i = RD->bases_begin();
+ if (i->isVirtual())
+ return false;
+ if (i->getAccessSpecifier() != AS_public)
+ return false;
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ if (Layout.getBaseClassOffset(Base) != 0)
+ return false;
+ return true;
+ }
+
+ llvm::Constant *finish(std::vector<llvm::Constant *> &info,
+ llvm::GlobalVariable *GV,
+ llvm::StringRef Name, bool Hidden) {
+ llvm::GlobalVariable::LinkageTypes linktype;
+ linktype = llvm::GlobalValue::LinkOnceODRLinkage;
+
+ llvm::Constant *C;
+ C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
+
+ if (GV == 0)
+ GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
+ linktype, C, Name);
+ else {
+ llvm::GlobalVariable *OGV = GV;
+ GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
+ linktype, C, Name);
+ GV->takeName(OGV);
+ llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
+ OGV->getType());
+ OGV->replaceAllUsesWith(NewPtr);
+ OGV->eraseFromParent();
+ }
+ if (Hidden)
+ GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+ }
+
+
+ llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
+ if (!CGM.getContext().getLangOptions().Rtti)
+ return llvm::Constant::getNullValue(Int8PtrTy);
+
+ llvm::Constant *C;
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
+ Out);
+
+ llvm::GlobalVariable *GV;
+ GV = CGM.getModule().getGlobalVariable(Out.str());
+ if (GV && !GV->isDeclaration())
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+
+ std::vector<llvm::Constant *> info;
+
+ bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
+
+ bool simple = false;
+ if (RD->getNumBases() == 0)
+ C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
+ else if (SimpleInheritance(RD)) {
+ simple = true;
+ C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
+ } else
+ C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
+ info.push_back(C);
+ info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden));
+
+ // If we have no bases, there are no more fields.
+ if (RD->getNumBases()) {
+ if (!simple) {
+ info.push_back(BuildFlags(CalculateFlags(RD)));
+ info.push_back(BuildBaseCount(RD->getNumBases()));
+ }
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(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());
+ info.push_back(CGM.GenerateRttiRef(Base));
+ if (simple)
+ break;
+ int64_t offset;
+ if (!i->isVirtual())
+ offset = Layout.getBaseClassOffset(Base)/8;
+ else
+ offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
+ offset <<= 8;
+ // Now set the flags.
+ offset += i->isVirtual() ? 1 : 0;;
+ offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
+ const llvm::Type *LongTy =
+ CGM.getTypes().ConvertType(CGM.getContext().LongTy);
+ C = llvm::ConstantInt::get(LongTy, offset);
+ info.push_back(C);
+ }
+ }
+
+ return finish(info, GV, Out.str(), Hidden);
+ }
+
+ /// - BuildFlags - Build a __flags value for __pbase_type_info.
+ llvm::Constant *BuildInt(int f) {
+ return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
+ }
+
+ llvm::Constant *BuildType2(QualType Ty) {
+ if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>())
+ if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()))
+ return Buildclass_type_info(RD);
+ return BuildType(Ty);
+ }
+
+ llvm::Constant *BuildPointerType(QualType Ty) {
+ llvm::Constant *C;
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
+
+ llvm::GlobalVariable *GV;
+ GV = CGM.getModule().getGlobalVariable(Out.str());
+ if (GV && !GV->isDeclaration())
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+
+ std::vector<llvm::Constant *> info;
+
+ // FIXME: pointer to hidden should be hidden, we should be able to
+ // grab a bit off the type for this.
+ bool Hidden = false;
+
+ QualType PTy = Ty->getPointeeType();
+ QualType BTy;
+ bool PtrMem = false;
+ if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(Ty)) {
+ PtrMem = true;
+ BTy = QualType(MPT->getClass(), 0);
+ PTy = MPT->getPointeeType();
+ }
+
+ if (PtrMem)
+ C = BuildVtableRef("_ZTVN10__cxxabiv129__pointer_to_member_type_infoE");
+ else
+ C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE");
+ info.push_back(C);
+ info.push_back(BuildName(Ty, Hidden));
+ Qualifiers Q = PTy.getQualifiers();
+ PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType();
+ int flags = 0;
+ flags += Q.hasConst() ? 0x1 : 0;
+ flags += Q.hasVolatile() ? 0x2 : 0;
+ flags += Q.hasRestrict() ? 0x4 : 0;
+ flags += Ty.getTypePtr()->isIncompleteType() ? 0x8 : 0;
+ if (PtrMem && BTy.getTypePtr()->isIncompleteType())
+ flags += 0x10;
+
+ info.push_back(BuildInt(flags));
+ info.push_back(BuildInt(0));
+ info.push_back(BuildType2(PTy));
+
+ if (PtrMem)
+ info.push_back(BuildType2(BTy));
+
+ return finish(info, GV, Out.str(), true);
+ }
+
+ llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) {
+ llvm::Constant *C;
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
+
+ llvm::GlobalVariable *GV;
+ GV = CGM.getModule().getGlobalVariable(Out.str());
+ if (GV && !GV->isDeclaration())
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+
+ std::vector<llvm::Constant *> info;
+
+ // FIXME: pointer to hidden should be hidden, we should be able to
+ // grab a bit off the type for this.
+ bool Hidden = false;
+
+ C = BuildVtableRef(vtbl);
+ info.push_back(C);
+ info.push_back(BuildName(Ty, Hidden));
+
+ return finish(info, GV, Out.str(), true);
+ }
+
+ llvm::Constant *BuildType(QualType Ty) {
+ const clang::Type &Type
+ = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
+ switch (Type.getTypeClass()) {
+ default: {
+ assert(0 && "typeid expression");
+ return llvm::Constant::getNullValue(Int8PtrTy);
+ }
+
+ case Type::Builtin: {
+ // We expect all type_info objects for builtin types to be in the library.
+ return BuildTypeRef(Ty);
+ }
+
+ case Type::Pointer: {
+ QualType PTy = Ty->getPointeeType();
+ Qualifiers Q = PTy.getQualifiers();
+ Q.removeConst();
+ // T* and const T* for all builtin types T are expected in the library.
+ if (isa<BuiltinType>(PTy) && Q.empty())
+ return BuildTypeRef(Ty);
+
+ return BuildPointerType(Ty);
+ }
+ case Type::MemberPointer:
+ return BuildPointerType(Ty);
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE");
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::Vector:
+ case Type::ExtVector:
+ return BuildSimpleType(Ty, "_ZTVN10__cxxabiv117__array_type_infoE");
+ case Type::Enum:
+ return BuildSimpleType(Ty, "_ZTVN10__cxxabiv116__enum_type_infoE");
+ }
+ }
+};
+
+llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) {
+ RttiBuilder b(*this);
+
+ return b.Buildclass_type_infoRef(RD);
+}
+
llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
-
- if (!getContext().getLangOptions().Rtti)
- return llvm::Constant::getNullValue(Int8PtrTy);
-
- llvm::SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- mangleCXXRtti(getMangleContext(), Context.getTagDeclType(RD), Out);
-
- llvm::GlobalVariable::LinkageTypes linktype;
- linktype = llvm::GlobalValue::WeakAnyLinkage;
- std::vector<llvm::Constant *> info;
- // assert(0 && "FIXME: implement rtti descriptor");
- // FIXME: descriptor
- info.push_back(llvm::Constant::getNullValue(Int8PtrTy));
- // assert(0 && "FIXME: implement rtti ts");
- // FIXME: TS
- info.push_back(llvm::Constant::getNullValue(Int8PtrTy));
-
- llvm::Constant *C;
- llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size());
- C = llvm::ConstantArray::get(type, info);
- llvm::Constant *Rtti =
- new llvm::GlobalVariable(getModule(), type, true, linktype, C,
- Out.str());
- Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy);
- return Rtti;
+ RttiBuilder b(*this);
+
+ return b.Buildclass_type_info(RD);
+}
+
+llvm::Constant *CodeGenModule::GenerateRttiNonClass(QualType Ty) {
+ RttiBuilder b(*this);
+
+ return b.BuildType(Ty);
}
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 9126c2c99cdf..b6d7b3990452 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -148,13 +148,8 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
CGDebugInfo *DI = getDebugInfo();
if (DI) {
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
DI->setLocation(S.getLBracLoc());
DI->EmitRegionStart(CurFn, Builder);
-#else
- EnsureInsertPoint();
- DI->setLocation(S.getLBracLoc());
-#endif
}
// Keep track of the current cleanup stack depth.
@@ -167,13 +162,8 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
EmitStmt(*I);
if (DI) {
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
DI->setLocation(S.getLBracLoc());
DI->EmitRegionEnd(CurFn, Builder);
-#else
- EnsureInsertPoint();
- DI->setLocation(S.getLBracLoc());
-#endif
}
RValue RV;
@@ -284,16 +274,9 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
- // Emit initial switch which will be patched up later by
- // EmitIndirectSwitches(). We need a default dest, so we use the
- // current BB, but this is overwritten.
-#ifndef USEINDIRECTBRANCH
- llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()),
- llvm::Type::getInt32Ty(VMContext),
-#else
+ // Ensure that we have an i8* for our PHI node.
llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
llvm::Type::getInt8PtrTy(VMContext),
-#endif
"addr");
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
@@ -491,13 +474,11 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock));
// If the condition is true, execute the body of the for stmt.
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
CGDebugInfo *DI = getDebugInfo();
if (DI) {
DI->setLocation(S.getSourceRange().getBegin());
DI->EmitRegionStart(CurFn, Builder);
}
-#endif
EmitStmt(S.getBody());
BreakContinueStack.pop_back();
@@ -510,12 +491,10 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// Finally, branch back up to the condition for the next iteration.
EmitBranch(CondBlock);
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
if (DI) {
DI->setLocation(S.getSourceRange().getEnd());
DI->EmitRegionEnd(CurFn, Builder);
}
-#endif
// Emit the fall-through block.
EmitBlock(AfterFor, true);
@@ -758,7 +737,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
}
static std::string
-SimplifyConstraint(const char *Constraint, TargetInfo &Target,
+SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
llvm::SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=0) {
std::string Result;
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index e2e11478de26..4c97a9bdeebf 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -15,6 +15,7 @@
#include "CodeGenFunction.h"
#include "clang/AST/RecordLayout.h"
+#include <cstdio>
using namespace clang;
using namespace CodeGen;
@@ -29,6 +30,11 @@ private:
llvm::Type *Ptr8Ty;
/// Class - The most derived class that this vtable is being built for.
const CXXRecordDecl *Class;
+ /// LayoutClass - The most derived class used for virtual base layout
+ /// information.
+ const CXXRecordDecl *LayoutClass;
+ /// LayoutOffset - The offset for Class in LayoutClass.
+ uint64_t LayoutOffset;
/// BLayout - Layout for the most derived class that this vtable is being
/// built for.
const ASTRecordLayout &BLayout;
@@ -39,38 +45,45 @@ private:
CodeGenModule &CGM; // Per-module state.
/// Index - Maps a method decl into a vtable index. Useful for virtual
/// dispatch codegen.
- llvm::DenseMap<const CXXMethodDecl *, Index_t> Index;
- llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
- llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
+ llvm::DenseMap<GlobalDecl, Index_t> Index;
+ llvm::DenseMap<GlobalDecl, Index_t> VCall;
+ llvm::DenseMap<GlobalDecl, Index_t> VCallOffset;
+ // This is the offset to the nearest virtual base
+ llvm::DenseMap<GlobalDecl, Index_t> NonVirtualOffset;
llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
- typedef llvm::DenseMap<const CXXMethodDecl *, int> Pures_t;
+ typedef llvm::DenseMap<GlobalDecl, int> Pures_t;
Pures_t Pures;
typedef std::pair<Index_t, Index_t> CallOffset;
- typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t;
+ typedef llvm::DenseMap<GlobalDecl, CallOffset> Thunks_t;
Thunks_t Thunks;
- typedef llvm::DenseMap<const CXXMethodDecl *,
+ typedef llvm::DenseMap<GlobalDecl,
std::pair<std::pair<CallOffset, CallOffset>,
CanQualType> > CovariantThunks_t;
CovariantThunks_t CovariantThunks;
std::vector<Index_t> VCalls;
+
+ typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
+ // CtorVtable - Used to hold the AddressPoints (offsets) into the built vtable
+ // for use in computing the initializers for the VTT.
+ llvm::DenseMap<CtorVtable_t, int64_t> &AddressPoints;
+
typedef CXXRecordDecl::method_iterator method_iter;
// FIXME: Linkage should follow vtable
const bool Extern;
const uint32_t LLVMPointerWidth;
Index_t extra;
- int CurrentVBaseOffset;
typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
llvm::Constant *cxa_pure;
public:
- VtableBuilder(std::vector<llvm::Constant *> &meth,
- const CXXRecordDecl *c,
- CodeGenModule &cgm)
- : methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)),
- rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()),
- CGM(cgm), Extern(true),
- LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)),
- CurrentVBaseOffset(0) {
+ VtableBuilder(std::vector<llvm::Constant *> &meth, const CXXRecordDecl *c,
+ const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm)
+ : methods(meth), Class(c), LayoutClass(l), LayoutOffset(lo),
+ BLayout(cgm.getContext().getASTRecordLayout(l)),
+ rtti(cgm.GenerateRttiRef(c)), VMContext(cgm.getModule().getContext()),
+ CGM(cgm), AddressPoints(*new llvm::DenseMap<CtorVtable_t, int64_t>),
+ Extern(true),
+ LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
// Calculate pointer for ___cxa_pure_virtual.
@@ -81,10 +94,13 @@ public:
cxa_pure = wrap(CGM.CreateRuntimeFunction(FTy, "__cxa_pure_virtual"));
}
- llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; }
+ llvm::DenseMap<GlobalDecl, Index_t> &getIndex() { return Index; }
llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
{ return VBIndex; }
+ llvm::DenseMap<CtorVtable_t, int64_t> *getAddressPoints()
+ { return &AddressPoints; }
+
llvm::Constant *wrap(Index_t i) {
llvm::Constant *m;
m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
@@ -95,8 +111,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) {
@@ -189,9 +205,11 @@ public:
return 0;
}
- bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
+ bool OverrideMethod(GlobalDecl GD, llvm::Constant *m,
bool MorallyVirtual, Index_t OverrideOffset,
- Index_t Offset) {
+ Index_t Offset, int64_t CurrentVBaseOffset) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
const bool isPure = MD->isPure();
typedef CXXMethodDecl::method_iterator meth_iter;
// FIXME: Should OverrideOffset's be Offset?
@@ -204,9 +222,16 @@ public:
for (meth_iter mi = MD->begin_overridden_methods(),
e = MD->end_overridden_methods();
mi != e; ++mi) {
+ GlobalDecl OGD;
+
const CXXMethodDecl *OMD = *mi;
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
+ OGD = GlobalDecl(DD, GD.getDtorType());
+ else
+ OGD = OMD;
+
llvm::Constant *om;
- om = CGM.GetAddrOfFunction(OMD, Ptr8Ty);
+ om = WrapAddrOf(OGD);
om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty);
for (Index_t i = 0, e = submethods.size();
@@ -229,57 +254,60 @@ public:
Index_t nv = getNVOffset(oret, ret)/8;
ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
}
- Index[MD] = i;
+ Index[GD] = i;
submethods[i] = m;
if (isPure)
- Pures[MD] = 1;
- Pures.erase(OMD);
- Thunks.erase(OMD);
- if (MorallyVirtual) {
- Index_t &idx = VCall[OMD];
+ Pures[GD] = 1;
+ Pures.erase(OGD);
+ Thunks.erase(OGD);
+ if (MorallyVirtual || VCall.count(OGD)) {
+ Index_t &idx = VCall[OGD];
if (idx == 0) {
- VCallOffset[MD] = OverrideOffset/8;
+ NonVirtualOffset[GD] = -OverrideOffset/8 + CurrentVBaseOffset/8;
+ VCallOffset[GD] = OverrideOffset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
- MD->getNameAsCString(),
- (int)-VCalls.size()-3, (int)VCallOffset[MD],
- Class->getNameAsCString()));
+ MD->getNameAsString().c_str(), (int)-idx-3,
+ (int)VCalls[idx-1], Class->getNameAsCString()));
} else {
- VCallOffset[MD] = VCallOffset[OMD];
- VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
+ 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->getNameAsCString(),
- (int)-VCalls.size()-3, (int)VCallOffset[MD],
- Class->getNameAsCString()));
+ MD->getNameAsString().c_str(), (int)-idx-3,
+ (int)VCalls[idx-1], Class->getNameAsCString()));
}
- VCall[MD] = idx;
- CallOffset ThisOffset;
- ThisOffset = std::make_pair(CurrentVBaseOffset/8 - Offset/8,
- -((idx+extra+2)*LLVMPointerWidth/8));
+ VCall[GD] = idx;
+ int64_t O = NonVirtualOffset[GD];
+ int v = -((idx+extra+2)*LLVMPointerWidth/8);
+ // Optimize out virtual adjustments of 0.
+ if (VCalls[idx-1] == 0)
+ v = 0;
+ CallOffset ThisOffset = std::make_pair(O, v);
// FIXME: Do we always have to build a covariant thunk to save oret,
// which is the containing virtual base class?
if (ReturnOffset.first || ReturnOffset.second)
- CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
+ CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
- else if (!isPure)
- Thunks[MD] = ThisOffset;
+ else if (!isPure && (ThisOffset.first || ThisOffset.second))
+ Thunks[GD] = ThisOffset;
return true;
}
// FIXME: finish off
- int64_t O = VCallOffset[OMD] - OverrideOffset/8;
- // int64_t O = CurrentVBaseOffset/8 - OverrideOffset/8;
+ int64_t O = VCallOffset[OGD] - OverrideOffset/8;
+
if (O || ReturnOffset.first || ReturnOffset.second) {
CallOffset ThisOffset = std::make_pair(O, 0);
if (ReturnOffset.first || ReturnOffset.second)
- CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
+ CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
else if (!isPure)
- Thunks[MD] = ThisOffset;
+ Thunks[GD] = ThisOffset;
}
return true;
}
@@ -291,9 +319,10 @@ public:
void InstallThunks() {
for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end();
i != e; ++i) {
- const CXXMethodDecl *MD = i->first;
+ GlobalDecl GD = i->first;
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
assert(!MD->isPure() && "Trying to thunk a pure");
- Index_t idx = Index[MD];
+ Index_t idx = Index[GD];
Index_t nv_O = i->second.first;
Index_t v_O = i->second.second;
submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O);
@@ -302,10 +331,11 @@ public:
for (CovariantThunks_t::iterator i = CovariantThunks.begin(),
e = CovariantThunks.end();
i != e; ++i) {
- const CXXMethodDecl *MD = i->first;
+ GlobalDecl GD = i->first;
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
if (MD->isPure())
continue;
- Index_t idx = Index[MD];
+ Index_t idx = Index[GD];
Index_t nv_t = i->second.first.first.first;
Index_t v_t = i->second.first.first.second;
Index_t nv_r = i->second.first.second.first;
@@ -316,16 +346,18 @@ public:
CovariantThunks.clear();
for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
i != e; ++i) {
- const CXXMethodDecl *MD = i->first;
- Index_t idx = Index[MD];
+ GlobalDecl GD = i->first;
+ Index_t idx = Index[GD];
submethods[idx] = cxa_pure;
}
Pures.clear();
}
- llvm::Constant *WrapAddrOf(const CXXMethodDecl *MD) {
+ llvm::Constant *WrapAddrOf(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
- return wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
+ return wrap(CGM.GetAddrOfCXXDestructor(Dtor, GD.getDtorType()));
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *Ty =
@@ -335,63 +367,95 @@ public:
return wrap(CGM.GetAddrOfFunction(MD, Ty));
}
- void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset) {
+ void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset,
+ int64_t CurrentVBaseOffset) {
for (Path_t::reverse_iterator i = Path->rbegin(),
e = Path->rend(); i != e; ++i) {
const CXXRecordDecl *RD = i->first;
int64_t OverrideOffset = i->second;
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi) {
- if (!mi->isVirtual())
+ const CXXMethodDecl *MD = *mi;
+
+ if (!MD->isVirtual())
continue;
- const CXXMethodDecl *MD = *mi;
- llvm::Constant *m = WrapAddrOf(MD);
- OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset);
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ // Override both the complete and the deleting destructor.
+ GlobalDecl CompDtor(DD, Dtor_Complete);
+ OverrideMethod(CompDtor, WrapAddrOf(CompDtor), MorallyVirtual,
+ OverrideOffset, Offset, CurrentVBaseOffset);
+
+ GlobalDecl DeletingDtor(DD, Dtor_Deleting);
+ OverrideMethod(DeletingDtor, WrapAddrOf(DeletingDtor), MorallyVirtual,
+ OverrideOffset, Offset, CurrentVBaseOffset);
+ } else {
+ OverrideMethod(MD, WrapAddrOf(MD), MorallyVirtual, OverrideOffset,
+ Offset, CurrentVBaseOffset);
+ }
}
}
}
- void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset,
- bool ForVirtualBase) {
- llvm::Constant *m = WrapAddrOf(MD);
+ void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset,
+ bool ForVirtualBase, int64_t CurrentVBaseOffset) {
+ llvm::Constant *m = WrapAddrOf(GD);
// If we can find a previously allocated slot for this, reuse it.
- if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset))
+ if (OverrideMethod(GD, m, MorallyVirtual, Offset, Offset,
+ CurrentVBaseOffset))
return;
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
// else allocate a new slot.
- Index[MD] = submethods.size();
+ Index[GD] = submethods.size();
submethods.push_back(m);
- D1(printf(" vfn for %s at %d\n", MD->getNameAsCString(), (int)Index[MD]));
+ D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
+ (int)Index[GD]));
if (MD->isPure())
- Pures[MD] = 1;
+ Pures[GD] = 1;
if (MorallyVirtual) {
- VCallOffset[MD] = Offset/8;
- Index_t &idx = VCall[MD];
+ VCallOffset[GD] = Offset/8;
+ Index_t &idx = VCall[GD];
// Allocate the first one, after that, we reuse the previous one.
if (idx == 0) {
+ NonVirtualOffset[GD] = CurrentVBaseOffset/8 - Offset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d\n",
- MD->getNameAsCString(), (int)-VCalls.size()-3,
- (int)VCallOffset[MD]));
+ MD->getNameAsString().c_str(), (int)-VCalls.size()-3, 0));
}
}
}
void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
- Index_t Offset, bool RDisVirtualBase) {
+ Index_t Offset, bool RDisVirtualBase,
+ int64_t CurrentVBaseOffset) {
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
- ++mi)
- if (mi->isVirtual())
- AddMethod(*mi, MorallyVirtual, Offset, RDisVirtualBase);
+ ++mi) {
+ const CXXMethodDecl *MD = *mi;
+ if (!MD->isVirtual())
+ continue;
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ // For destructors, add both the complete and the deleting destructor
+ // to the vtable.
+ AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset,
+ RDisVirtualBase, CurrentVBaseOffset);
+ AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset,
+ RDisVirtualBase, CurrentVBaseOffset);
+ } else
+ AddMethod(MD, MorallyVirtual, Offset, RDisVirtualBase,
+ CurrentVBaseOffset);
+ }
}
void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
const CXXRecordDecl *PrimaryBase,
bool PrimaryBaseWasVirtual, bool MorallyVirtual,
- int64_t Offset, Path_t *Path) {
+ int64_t Offset, int64_t CurrentVBaseOffset,
+ Path_t *Path) {
Path->push_back(std::make_pair(RD, Offset));
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
@@ -402,8 +466,8 @@ public:
if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
StartNewTable();
- CurrentVBaseOffset = Offset;
- GenerateVtableForBase(Base, MorallyVirtual, o, false, Path);
+ GenerateVtableForBase(Base, o, MorallyVirtual, false,
+ CurrentVBaseOffset, Path);
}
}
Path->pop_back();
@@ -424,11 +488,39 @@ public:
i != e; ++i)
methods[InsertionPoint++] = wrap((0?600:0) + *i);
VCalls.clear();
+ VCall.clear();
}
+ 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(),
+ LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
+ AddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
+
+ // Now also add the address point for all our primary bases.
+ while (1) {
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ RD = Layout.getPrimaryBase();
+ const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
+ // FIXME: Double check this.
+ if (RD == 0)
+ break;
+ if (PrimaryBaseWasVirtual &&
+ 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(),
+ LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
+ AddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
+ }
+ }
+
+
Index_t end(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual,
bool MorallyVirtual, int64_t Offset, bool ForVirtualBase,
+ int64_t CurrentVBaseOffset,
Path_t *Path) {
bool alloc = false;
if (Path == 0) {
@@ -446,7 +538,7 @@ public:
// FIXME: just for extra, or for all uses of VCalls.size post this?
extra = -VCalls.size();
- methods.push_back(wrap(-(Offset/8)));
+ methods.push_back(wrap(-((Offset-LayoutOffset)/8)));
methods.push_back(rtti);
Index_t AddressPoint = methods.size();
@@ -457,13 +549,22 @@ public:
// and then the non-virtual bases.
NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
- MorallyVirtual, Offset, Path);
+ MorallyVirtual, Offset, CurrentVBaseOffset, Path);
if (ForVirtualBase) {
- insertVCalls(VCallInsertionPoint);
+ // FIXME: We're adding to VCalls in callers, we need to do the overrides
+ // in the inner part, so that we know the complete set of vcalls during
+ // the build and don't have to insert into methods. Saving out the
+ // AddressPoint here, would need to be fixed, if we didn't do that. Also
+ // retroactively adding vcalls for overrides later wind up in the wrong
+ // place, the vcall slot has to be alloted during the walk of the base
+ // when the function is first introduces.
AddressPoint += VCalls.size();
+ insertVCalls(VCallInsertionPoint);
}
+ AddAddressPoints(RD, Offset, AddressPoint);
+
if (alloc) {
delete Path;
}
@@ -472,7 +573,7 @@ public:
void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
bool updateVBIndex, Index_t current_vbindex,
- bool RDisVirtualBase) {
+ bool RDisVirtualBase, int64_t CurrentVBaseOffset) {
if (!RD->isDynamicClass())
return;
@@ -485,21 +586,27 @@ public:
D1(printf(" doing primaries for %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
+ int BaseCurrentVBaseOffset = CurrentVBaseOffset;
+ if (PrimaryBaseWasVirtual)
+ BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
+
if (!PrimaryBaseWasVirtual)
Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
- updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
+ updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
+ BaseCurrentVBaseOffset);
}
D1(printf(" doing vcall entries for %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
// And add the virtuals for the class to the primary vtable.
- AddMethods(RD, MorallyVirtual, Offset, RDisVirtualBase);
+ AddMethods(RD, MorallyVirtual, Offset, RDisVirtualBase, CurrentVBaseOffset);
}
void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
bool updateVBIndex, Index_t current_vbindex,
- bool RDisVirtualBase, bool bottom=false) {
+ bool RDisVirtualBase, int64_t CurrentVBaseOffset,
+ bool bottom=false) {
if (!RD->isDynamicClass())
return;
@@ -509,14 +616,18 @@ public:
// vtables are composed from the chain of primaries.
if (PrimaryBase) {
- if (PrimaryBaseWasVirtual)
+ int BaseCurrentVBaseOffset = CurrentVBaseOffset;
+ if (PrimaryBaseWasVirtual) {
IndirectPrimary.insert(PrimaryBase);
+ BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase);
+ }
D1(printf(" doing primaries for %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
- updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
+ updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
+ BaseCurrentVBaseOffset);
}
D1(printf(" doing vbase entries for %s most derived %s\n",
@@ -525,17 +636,23 @@ public:
if (RDisVirtualBase || bottom) {
Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
- RDisVirtualBase);
+ RDisVirtualBase, CurrentVBaseOffset);
}
}
- int64_t GenerateVtableForBase(const CXXRecordDecl *RD,
- bool MorallyVirtual = false, int64_t Offset = 0,
+ int64_t GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
+ bool MorallyVirtual = false,
bool ForVirtualBase = false,
+ int CurrentVBaseOffset = 0,
Path_t *Path = 0) {
if (!RD->isDynamicClass())
return 0;
+ // Construction vtable don't need parts that have no virtual bases and
+ // aren't morally virtual.
+ if ((LayoutClass != Class) && RD->getNumVBases() == 0 && !MorallyVirtual)
+ return 0;
+
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
@@ -548,13 +665,13 @@ public:
extra = VCalls.size();
VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
- true);
+ CurrentVBaseOffset, true);
if (Path)
- OverrideMethods(Path, MorallyVirtual, Offset);
+ OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
return end(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual,
- Offset, ForVirtualBase, Path);
+ Offset, ForVirtualBase, CurrentVBaseOffset, Path);
}
void GenerateVtableForVBases(const CXXRecordDecl *RD,
@@ -578,16 +695,21 @@ public:
StartNewTable();
VCall.clear();
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
- CurrentVBaseOffset = BaseOffset;
+ int64_t CurrentVBaseOffset = BaseOffset;
D1(printf("vtable %s virtual base %s\n",
Class->getNameAsCString(), Base->getNameAsCString()));
- GenerateVtableForBase(Base, true, BaseOffset, true, Path);
+ GenerateVtableForBase(Base, BaseOffset, true, true, CurrentVBaseOffset,
+ Path);
}
- int64_t BaseOffset = Offset;
+ int64_t BaseOffset;
if (i->isVirtual())
BaseOffset = BLayout.getVBaseClassOffset(Base);
+ else {
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+ }
+
if (Base->getNumVBases()) {
- CurrentVBaseOffset = BaseOffset;
GenerateVtableForVBases(Base, BaseOffset, Path);
}
}
@@ -603,19 +725,17 @@ VtableBuilder::Index_t VtableBuilder::VBlookup(CXXRecordDecl *D,
return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
}
-int64_t CGVtableInfo::getMethodVtableIndex(const CXXMethodDecl *MD) {
- MD = MD->getCanonicalDecl();
-
- MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(MD);
+int64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
+ MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(GD);
if (I != MethodVtableIndices.end())
return I->second;
- const CXXRecordDecl *RD = MD->getParent();
+ const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
std::vector<llvm::Constant *> methods;
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
- VtableBuilder b(methods, RD, CGM);
+ VtableBuilder b(methods, RD, RD, 0, CGM);
D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -623,7 +743,7 @@ int64_t CGVtableInfo::getMethodVtableIndex(const CXXMethodDecl *MD) {
MethodVtableIndices.insert(b.getIndex().begin(),
b.getIndex().end());
- I = MethodVtableIndices.find(MD);
+ I = MethodVtableIndices.find(GD);
assert(I != MethodVtableIndices.end() && "Did not find index!");
return I->second;
}
@@ -640,7 +760,7 @@ int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
std::vector<llvm::Constant *> methods;
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
- VtableBuilder b(methods, RD, CGM);
+ VtableBuilder b(methods, RD, RD, 0, CGM);
D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -659,10 +779,15 @@ int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
return I->second;
}
-llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
+llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass,
+ const CXXRecordDecl *RD,
+ uint64_t Offset) {
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
- mangleCXXVtable(CGM.getMangleContext(), RD, Out);
+ if (LayoutClass != RD)
+ mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset/8, RD, Out);
+ else
+ mangleCXXVtable(getMangleContext(), RD, Out);
llvm::GlobalVariable::LinkageTypes linktype;
linktype = llvm::GlobalValue::LinkOnceODRLinkage;
@@ -670,23 +795,245 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
int64_t AddressPoint;
- VtableBuilder b(methods, RD, CGM);
+ VtableBuilder b(methods, RD, LayoutClass, Offset, *this);
D1(printf("vtable %s\n", RD->getNameAsCString()));
// First comes the vtables for all the non-virtual bases...
- AddressPoint = b.GenerateVtableForBase(RD);
+ AddressPoint = b.GenerateVtableForBase(RD, Offset);
// then the vtables for all the virtual bases.
- b.GenerateVtableForVBases(RD);
+ b.GenerateVtableForVBases(RD, Offset);
+
+ CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass];
+ if (ref == 0)
+ ref = new CodeGenModule::AddrMap_t;
+
+ (*ref)[RD] = b.getAddressPoints();
llvm::Constant *C;
llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size());
C = llvm::ConstantArray::get(type, methods);
- llvm::Value *vtable = new llvm::GlobalVariable(CGM.getModule(), type, true,
- linktype, C, Out.str());
- vtable = Builder.CreateBitCast(vtable, Ptr8Ty);
- vtable = Builder.CreateGEP(vtable,
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
- AddressPoint*LLVMPointerWidth/8));
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(getModule(), type,
+ true, linktype, C,
+ Out.str());
+ bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
+ if (Hidden)
+ GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
+ llvm::Constant *vtable = llvm::ConstantExpr::getBitCast(GV, Ptr8Ty);
+ llvm::Constant *AddressPointC;
+ uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0);
+ AddressPointC = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ AddressPoint*LLVMPointerWidth/8);
+ vtable = llvm::ConstantExpr::getInBoundsGetElementPtr(vtable, &AddressPointC,
+ 1);
+
return vtable;
}
+
+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;
+ CodeGenModule::AddrMap_t &AddressPoints;
+ // vtbl - A pointer to the vtable for Class.
+ llvm::Constant *ClassVtbl;
+ llvm::LLVMContext &VMContext;
+
+ /// BuildVtablePtr - Build up a referene to the given secondary vtable
+ llvm::Constant *BuildVtablePtr(llvm::Constant *vtbl,
+ const CXXRecordDecl *VtblClass,
+ const CXXRecordDecl *RD,
+ uint64_t Offset) {
+ int64_t AddressPoint;
+ AddressPoint = (*AddressPoints[VtblClass])[std::make_pair(RD, Offset)];
+ // FIXME: We can never have 0 address point. Do this for now so gepping
+ // retains the same structure.
+ 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));
+ uint32_t LLVMPointerWidth = CGM.getContext().Target.getPointerWidth(0);
+ llvm::Constant *init;
+ init = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ AddressPoint*LLVMPointerWidth/8);
+ init = llvm::ConstantExpr::getInBoundsGetElementPtr(vtbl, &init, 1);
+ return init;
+ }
+
+ /// 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 = BuildVtablePtr(vtbl, VtblClass, RD, Offset);
+ else {
+ init = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset);
+ subvtbl = dyn_cast<llvm::Constant>(init->getOperand(0));
+ subVtblClass = Base;
+ }
+ 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 *init;
+ const CXXRecordDecl *VtblClass;
+
+ // First comes the primary virtual table pointer...
+ if (MorallyVirtual) {
+ init = BuildVtablePtr(ClassVtbl, Class, RD, Offset);
+ VtblClass = Class;
+ } else {
+ init = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset);
+ VtblClass = RD;
+ }
+ llvm::Constant *vtbl = dyn_cast<llvm::Constant>(init->getOperand(0));
+ Inits.push_back(init);
+
+ // then the secondary VTTs....
+ SecondaryVTTs(RD, Offset, MorallyVirtual);
+
+ // and last the secondary vtable pointers.
+ Secondary(RD, vtbl, VtblClass, 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, true);
+ }
+ VirtualVTTs(Base);
+ }
+ }
+public:
+ VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
+ CodeGenModule &cgm)
+ : Inits(inits), Class(c), CGM(cgm),
+ BLayout(cgm.getContext().getASTRecordLayout(c)),
+ AddressPoints(*cgm.AddressPoints[c]),
+ VMContext(cgm.getModule().getContext()) {
+
+ // First comes the primary virtual table pointer for the complete class...
+ ClassVtbl = CGM.getVtableInfo().getVtable(Class);
+ Inits.push_back(ClassVtbl);
+ ClassVtbl = dyn_cast<llvm::Constant>(ClassVtbl->getOperand(0));
+
+ // then the secondary VTTs...
+ SecondaryVTTs(Class);
+
+ // then the secondary vtable pointers...
+ Secondary(Class, ClassVtbl, Class);
+
+ // and last, the virtual VTTs.
+ VirtualVTTs(Class);
+ }
+};
+
+llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) {
+ // Only classes that have virtual bases need a VTT.
+ if (RD->getNumVBases() == 0)
+ return 0;
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXVTT(getMangleContext(), RD, Out);
+
+ llvm::GlobalVariable::LinkageTypes linktype;
+ linktype = llvm::GlobalValue::LinkOnceODRLinkage;
+ std::vector<llvm::Constant *> inits;
+ llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
+
+ D1(printf("vtt %s\n", RD->getNameAsCString()));
+
+ VTTBuilder b(inits, RD, *this);
+
+ llvm::Constant *C;
+ llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, inits.size());
+ C = llvm::ConstantArray::get(type, inits);
+ llvm::GlobalVariable *vtt = new llvm::GlobalVariable(getModule(), type, true,
+ linktype, C, Out.str());
+ bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
+ if (Hidden)
+ vtt->setVisibility(llvm::GlobalVariable::HiddenVisibility);
+ return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty);
+}
+
+llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
+ llvm::Constant *&vtbl = Vtables[RD];
+ if (vtbl)
+ return vtbl;
+ vtbl = CGM.GenerateVtable(RD, RD);
+ CGM.GenerateRtti(RD);
+ CGM.GenerateVTT(RD);
+ return vtbl;
+}
+
+llvm::Constant *CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass,
+ const CXXRecordDecl *RD,
+ uint64_t Offset) {
+ return CGM.GenerateVtable(LayoutClass, RD, Offset);
+}
diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h
index 69fb1f100599..f9ddf44284b1 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -15,6 +15,7 @@
#define CLANG_CODEGEN_CGVTABLE_H
#include "llvm/ADT/DenseMap.h"
+#include "GlobalDecl.h"
namespace clang {
class CXXMethodDecl;
@@ -28,7 +29,7 @@ class CGVtableInfo {
/// MethodVtableIndices - Contains the index (relative to the vtable address
/// point) where the function pointer for a virtual function is stored.
- typedef llvm::DenseMap<const CXXMethodDecl *, int64_t> MethodVtableIndicesTy;
+ typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVtableIndicesTy;
MethodVtableIndicesTy MethodVtableIndices;
typedef std::pair<const CXXRecordDecl *,
@@ -38,6 +39,8 @@ class CGVtableInfo {
/// offsets for virtual bases of a class are stored.
typedef llvm::DenseMap<ClassPairTy, int64_t> VirtualBaseClassIndiciesTy;
VirtualBaseClassIndiciesTy VirtualBaseClassIndicies;
+
+ llvm::DenseMap<const CXXRecordDecl *, llvm::Constant *> Vtables;
public:
CGVtableInfo(CodeGenModule &CGM)
: CGM(CGM) { }
@@ -45,7 +48,7 @@ public:
/// getMethodVtableIndex - Return the index (relative to the vtable address
/// point) where the function pointer for the given virtual function is
/// stored.
- int64_t getMethodVtableIndex(const CXXMethodDecl *MD);
+ int64_t getMethodVtableIndex(GlobalDecl GD);
/// getVirtualBaseOffsetIndex - Return the index (relative to the vtable
/// address point) where the offset of the virtual base that contains the
@@ -54,6 +57,10 @@ public:
/// base.
int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase);
+
+ llvm::Constant *getVtable(const CXXRecordDecl *RD);
+ llvm::Constant *getCtorVtable(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class, uint64_t Offset);
};
}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 4be341311ce4..475c7bfefd1d 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -27,11 +27,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
: BlockFunction(cgm, *this, Builder), CGM(cgm),
Target(CGM.getContext().Target),
Builder(cgm.getModule().getContext()),
-#ifndef USEINDIRECTBRANCH
- DebugInfo(0), IndirectGotoSwitch(0),
-#else
DebugInfo(0), IndirectBranch(0),
-#endif
SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
CXXThisDecl(0) {
LLVMIntTy = ConvertType(getContext().IntTy);
@@ -134,7 +130,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EmitFunctionEpilog(*CurFnInfo, ReturnValue);
-#ifdef USEINDIRECTBRANCH
// If someone did an indirect goto, emit the indirect goto block at the end of
// the function.
if (IndirectBranch) {
@@ -142,13 +137,10 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
Builder.ClearInsertionPoint();
}
-
-#endif
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
AllocaInsertPt = 0;
Ptr->eraseFromParent();
-#ifdef USEINDIRECTBRANCH
// If someone took the address of a label but never did an indirect goto, we
// made a zero entry PHI node, which is illegal, zap it now.
@@ -159,8 +151,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
PN->eraseFromParent();
}
}
-
-#endif
}
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
@@ -260,19 +250,21 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD,
// FIXME: Support CXXTryStmt here, too.
if (const CompoundStmt *S = FD->getCompoundBody()) {
StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc());
- const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD);
- llvm::BasicBlock *DtorEpilogue = 0;
- if (DD) {
- DtorEpilogue = createBasicBlock("dtor.epilogue");
-
- PushCleanupBlock(DtorEpilogue);
- }
-
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
+
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
EmitCtorPrologue(CD, GD.getCtorType());
- EmitStmt(S);
+ EmitStmt(S);
+
+ // If any of the member initializers are temporaries bound to references
+ // make sure to emit their destructors.
+ EmitCleanupBlocks(0);
+
+ } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
+ llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
+ PushCleanupBlock(DtorEpilogue);
+
+ EmitStmt(S);
- if (DD) {
CleanupBlockInfo Info = PopCleanupBlock();
assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
@@ -283,7 +275,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD,
EmitBlock(Info.SwitchBlock);
if (Info.EndBlock)
EmitBlock(Info.EndBlock);
+ } else {
+ // Just a regular function, emit its body.
+ EmitStmt(S);
}
+
FinishFunction(S->getRBracLoc());
} else if (FD->isImplicit()) {
const CXXRecordDecl *ClassDecl =
@@ -493,121 +489,32 @@ void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) {
TypeInfo.second/8));
}
-#ifndef USEINDIRECTBRANCH
-unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
- // Use LabelIDs.size()+1 as the new ID if one hasn't been assigned.
- unsigned &Entry = LabelIDs[L];
- if (Entry) return Entry;
-#else
-
llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {
// Make sure that there is a block for the indirect goto.
if (IndirectBranch == 0)
GetIndirectGotoBlock();
-#endif
-#ifndef USEINDIRECTBRANCH
- Entry = LabelIDs.size();
-#else
llvm::BasicBlock *BB = getBasicBlockForLabel(L);
-#endif
-
-#ifndef USEINDIRECTBRANCH
- // If this is the first "address taken" of a label and the indirect goto has
- // already been seen, add this to it.
- if (IndirectGotoSwitch) {
- // If this is the first address-taken label, set it as the default dest.
- if (Entry == 1)
- IndirectGotoSwitch->setSuccessor(0, getBasicBlockForLabel(L));
- else {
- // Otherwise add it to the switch as a new dest.
- const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext);
- IndirectGotoSwitch->addCase(llvm::ConstantInt::get(Int32Ty, Entry),
- getBasicBlockForLabel(L));
- }
- }
- return Entry;
-#else
// Make sure the indirect branch includes all of the address-taken blocks.
IndirectBranch->addDestination(BB);
return llvm::BlockAddress::get(CurFn, BB);
-#endif
}
llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
-#ifndef USEINDIRECTBRANCH
- // If we already made the switch stmt for indirect goto, return its block.
- if (IndirectGotoSwitch) return IndirectGotoSwitch->getParent();
-#else
// If we already made the indirect branch for indirect goto, return its block.
if (IndirectBranch) return IndirectBranch->getParent();
-#endif
-#ifndef USEINDIRECTBRANCH
- EmitBlock(createBasicBlock("indirectgoto"));
-#else
CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto"));
-#endif
-#ifndef USEINDIRECTBRANCH
- const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext);
-#else
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
-#endif
// Create the PHI node that indirect gotos will add entries to.
-#ifndef USEINDIRECTBRANCH
- llvm::Value *DestVal = Builder.CreatePHI(Int32Ty, "indirect.goto.dest");
-#else
llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, "indirect.goto.dest");
-#endif
-
-#ifndef USEINDIRECTBRANCH
- // Create the switch instruction. For now, set the insert block to this block
- // which will be fixed as labels are added.
- IndirectGotoSwitch = Builder.CreateSwitch(DestVal, Builder.GetInsertBlock());
-
- // Clear the insertion point to indicate we are in unreachable code.
- Builder.ClearInsertionPoint();
- // If we already have labels created, add them.
- if (!LabelIDs.empty()) {
- // Invert LabelID's so that the order is determinstic.
- std::vector<const LabelStmt*> AddrTakenLabelsByID;
- AddrTakenLabelsByID.resize(LabelIDs.size());
-
- for (std::map<const LabelStmt*,unsigned>::iterator
- LI = LabelIDs.begin(), LE = LabelIDs.end(); LI != LE; ++LI) {
- assert(LI->second-1 < AddrTakenLabelsByID.size() &&
- "Numbering inconsistent");
- AddrTakenLabelsByID[LI->second-1] = LI->first;
- }
-
- // Set the default entry as the first block.
- IndirectGotoSwitch->setSuccessor(0,
- getBasicBlockForLabel(AddrTakenLabelsByID[0]));
-
- // FIXME: The iteration order of this is nondeterminstic!
- for (unsigned i = 1, e = AddrTakenLabelsByID.size(); i != e; ++i)
- IndirectGotoSwitch->addCase(llvm::ConstantInt::get(Int32Ty, i+1),
- getBasicBlockForLabel(AddrTakenLabelsByID[i]));
- } else {
- // Otherwise, create a dead block and set it as the default dest. This will
- // be removed by the optimizers after the indirect goto is set up.
- llvm::BasicBlock *Dummy = createBasicBlock("indgoto.dummy");
- EmitBlock(Dummy);
- IndirectGotoSwitch->setSuccessor(0, Dummy);
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
- }
-
- return IndirectGotoSwitch->getParent();
-#else
// Create the indirect branch instruction.
IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
return IndirectBranch->getParent();
-#endif
}
llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index fe8113e95332..d96c3551010e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -74,7 +74,7 @@ class CodeGenFunction : public BlockFunction {
void operator=(const CodeGenFunction&); // DO NOT IMPLEMENT
public:
CodeGenModule &CGM; // Per-module state.
- TargetInfo &Target;
+ const TargetInfo &Target;
typedef std::pair<llvm::Value *, llvm::Value *> ComplexPairTy;
CGBuilderTy Builder;
@@ -193,28 +193,12 @@ public:
private:
CGDebugInfo *DebugInfo;
-#ifndef USEINDIRECTBRANCH
- /// LabelIDs - Track arbitrary ids assigned to labels for use in implementing
- /// the GCC address-of-label extension and indirect goto. IDs are assigned to
- /// labels inside getIDForAddrOfLabel().
- std::map<const LabelStmt*, unsigned> LabelIDs;
-#else
/// IndirectBranch - The first time an indirect goto is seen we create a
/// block with an indirect branch. Every time we see the address of a label
/// taken, we add the label to the indirect goto. Every subsequent indirect
/// goto is codegen'd as a jump to the IndirectBranch's basic block.
llvm::IndirectBrInst *IndirectBranch;
-#endif
-
-#ifndef USEINDIRECTBRANCH
- /// IndirectGotoSwitch - The first time an indirect goto is seen we create a
- /// block with the switch for the indirect gotos. Every time we see the
- /// address of a label taken, we add the label to the indirect goto. Every
- /// subsequent indirect goto is codegen'd as a jump to the
- /// IndirectGotoSwitch's basic block.
- llvm::SwitchInst *IndirectGotoSwitch;
-#endif
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
/// decls.
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
@@ -397,9 +381,6 @@ public:
/// legal to call this function even if there is no current insertion point.
void FinishFunction(SourceLocation EndLoc=SourceLocation());
- /// GenerateVtable - Generate the vtable for the given type.
- llvm::Value *GenerateVtable(const CXXRecordDecl *RD);
-
/// DynamicTypeAdjust - Do the non-virtual and virtual adjustments on an
/// object pointer to alter the dynamic type of the pointer. Used by
/// GenerateCovariantThunk for building thunks.
@@ -586,11 +567,7 @@ public:
/// the input field number being accessed.
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
-#ifndef USEINDIRECTBRANCH
- unsigned GetIDForAddrOfLabel(const LabelStmt *L);
-#else
llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
-#endif
llvm::BasicBlock *GetIndirectGotoBlock();
/// EmitMemSetToZero - Generate code to memset a value of the given type to 0.
@@ -669,6 +646,14 @@ public:
const ArrayType *Array,
llvm::Value *This);
+ void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+ llvm::Value *NumElements,
+ llvm::Value *This);
+
+ llvm::Constant * GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This);
+
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
llvm::Value *This);
@@ -678,6 +663,12 @@ public:
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
+ void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr,
+ QualType DeleteTy);
+
+ llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
+ llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
+
//===--------------------------------------------------------------------===//
// Declaration Emission
//===--------------------------------------------------------------------===//
@@ -851,17 +842,18 @@ public:
LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E);
- LValue EmitPointerToDataMemberLValue(const DeclRefExpr *E);
+
+ LValue EmitPointerToDataMemberLValue(const FieldDecl *Field);
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
- LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
+ LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field,
bool isUnion, unsigned CVRQualifiers);
LValue EmitLValueForIvar(QualType ObjectTy,
llvm::Value* Base, const ObjCIvarDecl *Ivar,
unsigned CVRQualifiers);
- LValue EmitLValueForBitfield(llvm::Value* Base, FieldDecl* Field,
+ LValue EmitLValueForBitfield(llvm::Value* Base, const FieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitBlockDeclRefLValue(const BlockDeclRefExpr *E);
@@ -870,6 +862,7 @@ public:
LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
LValue EmitCXXExprWithTemporariesLValue(const CXXExprWithTemporaries *E);
+ LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E);
LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E);
LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E);
@@ -901,8 +894,11 @@ public:
const Decl *TargetDecl = 0);
RValue EmitCallExpr(const CallExpr *E);
- llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This,
+ llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
const llvm::Type *Ty);
+ llvm::Value *BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
+ llvm::Value *&This, const llvm::Type *Ty);
+
RValue EmitCXXMemberCall(const CXXMethodDecl *MD,
llvm::Value *Callee,
llvm::Value *This,
@@ -1016,7 +1012,7 @@ public:
/// EmitCXXGlobalDtorRegistration - Emits a call to register the global ptr
/// with the C++ runtime so that its destructor will be called at exit.
- void EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor,
+ void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr);
/// GenerateCXXGlobalInitFunc - Generates code for initializing global
@@ -1033,7 +1029,7 @@ public:
bool IsInitializer = false);
void EmitCXXThrowExpr(const CXXThrowExpr *E);
-
+
//===--------------------------------------------------------------------===//
// Internal Helpers
//===--------------------------------------------------------------------===//
@@ -1101,6 +1097,7 @@ private:
if (CallArgTypeInfo) {
for (typename T::arg_type_iterator I = CallArgTypeInfo->arg_type_begin(),
E = CallArgTypeInfo->arg_type_end(); I != E; ++I, ++Arg) {
+ assert(Arg != ArgEnd && "Running over edge of argument list!");
QualType ArgType = *I;
assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index db609f62453c..0e6f4a63a42c 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -17,7 +17,7 @@
#include "CGCall.h"
#include "CGObjCRuntime.h"
#include "Mangle.h"
-#include "clang/Frontend/CompileOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
@@ -30,15 +30,16 @@
#include "llvm/Module.h"
#include "llvm/Intrinsics.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
using namespace CodeGen;
-CodeGenModule::CodeGenModule(ASTContext &C, const CompileOptions &compileOpts,
+CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
llvm::Module &M, const llvm::TargetData &TD,
Diagnostic &diags)
: BlockModule(C, M, TD, Types, *this), Context(C),
- Features(C.getLangOptions()), CompileOpts(compileOpts), TheModule(M),
+ Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M),
TheTargetData(TD), Diags(diags), Types(C, M, TD), MangleCtx(C),
VtableInfo(*this), Runtime(0),
MemCpyFn(0), MemMoveFn(0), MemSetFn(0), CFConstantStringClassRef(0),
@@ -54,7 +55,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CompileOptions &compileOpts,
Runtime = CreateMacObjCRuntime(*this);
// If debug info generation is enabled, create the CGDebugInfo object.
- DebugInfo = CompileOpts.DebugInfo ? new CGDebugInfo(this) : 0;
+ DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(this) : 0;
}
CodeGenModule::~CodeGenModule() {
@@ -347,6 +348,11 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (D->hasAttr<NoInlineAttr>())
F->addFnAttr(llvm::Attribute::NoInline);
+ if (Features.getStackProtectorMode() == LangOptions::SSPOn)
+ F->addFnAttr(llvm::Attribute::StackProtect);
+ else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
+ F->addFnAttr(llvm::Attribute::StackProtectReq);
+
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
F->setAlignment(AA->getAlignment()/8);
// C++ ABI requires 2-byte alignment for member functions.
@@ -543,10 +549,15 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
// Static data may be deferred, but out-of-line static data members
// cannot be.
- // FIXME: What if the initializer has side effects?
- return VD->isInAnonymousNamespace() ||
- (VD->getStorageClass() == VarDecl::Static &&
- !(VD->isStaticDataMember() && VD->isOutOfLine()));
+ if (VD->isInAnonymousNamespace())
+ return true;
+ if (VD->getStorageClass() == VarDecl::Static) {
+ // Initializer has side effects?
+ if (VD->getInit() && VD->getInit()->HasSideEffects(Context))
+ return false;
+ return !(VD->isStaticDataMember() && VD->isOutOfLine());
+ }
+ return false;
}
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
@@ -639,6 +650,24 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
return llvm::ConstantExpr::getBitCast(Entry, PTy);
}
+ // This function doesn't have a complete type (for example, the return
+ // type is an incomplete struct). Use a fake type instead, and make
+ // sure not to try to set attributes.
+ bool IsIncompleteFunction = false;
+ if (!isa<llvm::FunctionType>(Ty)) {
+ Ty = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ std::vector<const llvm::Type*>(), false);
+ IsIncompleteFunction = true;
+ }
+ llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
+ llvm::Function::ExternalLinkage,
+ "", &getModule());
+ F->setName(MangledName);
+ if (D.getDecl())
+ SetFunctionAttributes(cast<FunctionDecl>(D.getDecl()), F,
+ IsIncompleteFunction);
+ Entry = F;
+
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
// of the file.
@@ -672,23 +701,6 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
DeferredCopyAssignmentToEmit(D);
}
- // This function doesn't have a complete type (for example, the return
- // type is an incomplete struct). Use a fake type instead, and make
- // sure not to try to set attributes.
- bool IsIncompleteFunction = false;
- if (!isa<llvm::FunctionType>(Ty)) {
- Ty = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- std::vector<const llvm::Type*>(), false);
- IsIncompleteFunction = true;
- }
- llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
- llvm::Function::ExternalLinkage,
- "", &getModule());
- F->setName(MangledName);
- if (D.getDecl())
- SetFunctionAttributes(cast<FunctionDecl>(D.getDecl()), F,
- IsIncompleteFunction);
- Entry = F;
return F;
}
@@ -1075,7 +1087,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
} else if (Linkage == GVA_TemplateInstantiation)
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
- else if (!CompileOpts.NoCommon &&
+ else if (!CodeGenOpts.NoCommon &&
!D->hasExternalStorage() && !D->getInit() &&
!D->getAttr<SectionAttr>()) {
GV->setLinkage(llvm::GlobalVariable::CommonLinkage);
@@ -1548,7 +1560,14 @@ std::string CodeGenModule::GetStringForStringLiteral(const StringLiteral *E) {
llvm::Constant *
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
// FIXME: This can be more efficient.
- return GetAddrOfConstantString(GetStringForStringLiteral(S));
+ // FIXME: We shouldn't need to bitcast the constant in the wide string case.
+ llvm::Constant *C = GetAddrOfConstantString(GetStringForStringLiteral(S));
+ if (S->isWide()) {
+ llvm::Type *DestTy =
+ llvm::PointerType::getUnqual(getTypes().ConvertType(S->getType()));
+ C = llvm::ConstantExpr::getBitCast(C, DestTy);
+ }
+ return C;
}
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
@@ -1697,6 +1716,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitNamespace(cast<NamespaceDecl>(D));
break;
// No code generation needed.
+ case Decl::UsingShadow:
case Decl::Using:
case Decl::UsingDirective:
case Decl::ClassTemplate:
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 2e58337ee52d..c8562d6745eb 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -23,6 +23,7 @@
#include "CGCXX.h"
#include "CGVtable.h"
#include "CodeGenTypes.h"
+#include "GlobalDecl.h"
#include "Mangle.h"
#include "llvm/Module.h"
#include "llvm/ADT/DenseMap.h"
@@ -31,8 +32,6 @@
#include "llvm/Support/ValueHandle.h"
#include <list>
-#define ATTACH_DEBUG_INFO_TO_AN_INSN 1
-
namespace llvm {
class Module;
class Constant;
@@ -61,7 +60,7 @@ namespace clang {
class ValueDecl;
class VarDecl;
class LangOptions;
- class CompileOptions;
+ class CodeGenOptions;
class Diagnostic;
class AnnotateAttr;
class CXXDestructorDecl;
@@ -72,46 +71,7 @@ namespace CodeGen {
class CGDebugInfo;
class CGObjCRuntime;
-/// GlobalDecl - represents a global declaration. This can either be a
-/// CXXConstructorDecl and the constructor type (Base, Complete).
-/// a CXXDestructorDecl and the destructor type (Base, Complete) or
-/// a VarDecl, a FunctionDecl or a BlockDecl.
-class GlobalDecl {
- llvm::PointerIntPair<const Decl*, 2> Value;
-
- void Init(const Decl *D) {
- assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
- assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
-
- Value.setPointer(D);
- }
-public:
- GlobalDecl() {}
-
- GlobalDecl(const VarDecl *D) { Init(D);}
- GlobalDecl(const FunctionDecl *D) { Init(D); }
- GlobalDecl(const BlockDecl *D) { Init(D); }
- GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
-
- GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
- : Value(D, Type) {}
- GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
- : Value(D, Type) {}
-
- const Decl *getDecl() const { return Value.getPointer(); }
-
- CXXCtorType getCtorType() const {
- assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
- return static_cast<CXXCtorType>(Value.getInt());
- }
-
- CXXDtorType getDtorType() const {
- assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
- return static_cast<CXXDtorType>(Value.getInt());
- }
-};
-
/// CodeGenModule - This class organizes the cross-function state that is used
/// while generating LLVM code.
class CodeGenModule : public BlockModule {
@@ -122,7 +82,7 @@ class CodeGenModule : public BlockModule {
ASTContext &Context;
const LangOptions &Features;
- const CompileOptions &CompileOpts;
+ const CodeGenOptions &CodeGenOpts;
llvm::Module &TheModule;
const llvm::TargetData &TheTargetData;
Diagnostic &Diags;
@@ -201,7 +161,7 @@ class CodeGenModule : public BlockModule {
llvm::LLVMContext &VMContext;
public:
- CodeGenModule(ASTContext &C, const CompileOptions &CompileOpts,
+ CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
llvm::Module &M, const llvm::TargetData &TD, Diagnostic &Diags);
~CodeGenModule();
@@ -222,7 +182,7 @@ public:
CGDebugInfo *getDebugInfo() { return DebugInfo; }
ASTContext &getContext() const { return Context; }
- const CompileOptions &getCompileOpts() const { return CompileOpts; }
+ const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
const LangOptions &getLangOptions() const { return Features; }
llvm::Module &getModule() const { return TheModule; }
CodeGenTypes &getTypes() { return Types; }
@@ -252,8 +212,26 @@ public:
llvm::Constant *GetAddrOfFunction(GlobalDecl GD,
const llvm::Type *Ty = 0);
+ /// GenerateVtable - Generate the vtable for the given type. LayoutClass is
+ /// the class to use for the virtual base layout information. For
+ /// non-construction vtables, this is always the same as RD. Offset is the
+ /// offset in bits for the RD object in the LayoutClass, if we're generating a
+ /// construction vtable, otherwise 0.
+ llvm::Constant *GenerateVtable(const CXXRecordDecl *LayoutClass,
+ const CXXRecordDecl *RD,
+ uint64_t Offset=0);
+
+ /// GenerateVTT - Generate the VTT for the given type.
+ llvm::Constant *GenerateVTT(const CXXRecordDecl *RD);
+
/// GenerateRtti - Generate the rtti information for the given type.
llvm::Constant *GenerateRtti(const CXXRecordDecl *RD);
+ /// GenerateRttiRef - Generate a reference to the rtti information for the
+ /// given type.
+ llvm::Constant *GenerateRttiRef(const CXXRecordDecl *RD);
+ /// GenerateRttiNonClass - Generate the rtti information for the given
+ /// non-class type.
+ llvm::Constant *GenerateRttiNonClass(QualType Ty);
/// BuildThunk - Build a thunk for the given method
llvm::Constant *BuildThunk(const CXXMethodDecl *MD, bool Extern, int64_t nv,
@@ -263,6 +241,11 @@ public:
int64_t nv_t, int64_t v_t,
int64_t nv_r, int64_t v_r);
+ typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
+ typedef llvm::DenseMap<const CXXRecordDecl *,
+ llvm::DenseMap<CtorVtable_t, int64_t>*> AddrMap_t;
+ llvm::DenseMap<const CXXRecordDecl *, AddrMap_t*> AddressPoints;
+
/// GetCXXBaseClassOffset - Returns the offset from a derived class to its
/// base class. Returns null if the offset is 0.
llvm::Constant *GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl,
@@ -499,7 +482,7 @@ private:
/// EmitCXXGlobalInitFunc - Emit a function that initializes C++ globals.
void EmitCXXGlobalInitFunc();
-
+
// FIXME: Hardcoding priority here is gross.
void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);
void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535);
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index d43d13e26bbb..1f83f37e0479 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -492,7 +492,7 @@ const CGRecordLayout &
CodeGenTypes::getCGRecordLayout(const TagDecl *TD) const {
const Type *Key =
Context.getTagDeclType(TD).getTypePtr();
- llvm::DenseMap<const Type*, CGRecordLayout *>::iterator I
+ llvm::DenseMap<const Type*, CGRecordLayout *>::const_iterator I
= CGRecordLayouts.find(Key);
assert (I != CGRecordLayouts.end()
&& "Unable to find record layout information for type");
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index a92a019b988e..f447549f669c 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -91,7 +91,7 @@ namespace CodeGen {
/// while lowering AST types to LLVM types.
class CodeGenTypes {
ASTContext &Context;
- TargetInfo &Target;
+ const TargetInfo &Target;
llvm::Module& TheModule;
const llvm::TargetData& TheTargetData;
mutable const ABIInfo* TheABIInfo;
@@ -153,7 +153,7 @@ public:
~CodeGenTypes();
const llvm::TargetData &getTargetData() const { return TheTargetData; }
- TargetInfo &getTarget() const { return Target; }
+ const TargetInfo &getTarget() const { return Target; }
ASTContext &getContext() const { return Context; }
const ABIInfo &getABIInfo() const;
llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
diff --git a/lib/CodeGen/GlobalDecl.h b/lib/CodeGen/GlobalDecl.h
new file mode 100644
index 000000000000..b812020f2aa4
--- /dev/null
+++ b/lib/CodeGen/GlobalDecl.h
@@ -0,0 +1,110 @@
+//===--- GlobalDecl.h - Global declaration holder ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor
+// together with its type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_GLOBALDECL_H
+#define CLANG_CODEGEN_GLOBALDECL_H
+
+namespace clang {
+
+namespace CodeGen {
+
+/// GlobalDecl - represents a global declaration. This can either be a
+/// CXXConstructorDecl and the constructor type (Base, Complete).
+/// a CXXDestructorDecl and the destructor type (Base, Complete) or
+/// a VarDecl, a FunctionDecl or a BlockDecl.
+class GlobalDecl {
+ llvm::PointerIntPair<const Decl*, 2> Value;
+
+ void Init(const Decl *D) {
+ assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
+ assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
+
+ Value.setPointer(D);
+ }
+
+public:
+ GlobalDecl() {}
+
+ GlobalDecl(const VarDecl *D) { Init(D);}
+ GlobalDecl(const FunctionDecl *D) { Init(D); }
+ GlobalDecl(const BlockDecl *D) { Init(D); }
+ GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
+
+ GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
+ : Value(D, Type) {}
+ GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
+ : Value(D, Type) {}
+
+ const Decl *getDecl() const { return Value.getPointer(); }
+
+ CXXCtorType getCtorType() const {
+ assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
+ return static_cast<CXXCtorType>(Value.getInt());
+ }
+
+ CXXDtorType getDtorType() const {
+ assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
+ return static_cast<CXXDtorType>(Value.getInt());
+ }
+
+ friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
+ return LHS.Value == RHS.Value;
+ }
+
+ void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
+
+ static GlobalDecl getFromOpaquePtr(void *P) {
+ GlobalDecl GD;
+ GD.Value.setFromOpaqueValue(P);
+ return GD;
+ }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+namespace llvm {
+ template<class> struct DenseMapInfo;
+
+ template<> struct DenseMapInfo<clang::CodeGen::GlobalDecl> {
+ static inline clang::CodeGen::GlobalDecl getEmptyKey() {
+ return clang::CodeGen::GlobalDecl();
+ }
+
+ static inline clang::CodeGen::GlobalDecl getTombstoneKey() {
+ return clang::CodeGen::GlobalDecl::
+ getFromOpaquePtr(reinterpret_cast<void*>(-1));
+ }
+
+ static unsigned getHashValue(clang::CodeGen::GlobalDecl GD) {
+ return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
+ }
+
+ static bool isEqual(clang::CodeGen::GlobalDecl LHS,
+ clang::CodeGen::GlobalDecl RHS) {
+ return LHS == RHS;
+ }
+
+ static bool isPod() {
+ // GlobalDecl isn't *technically* a POD type. However, we can get
+ // away with calling it a POD type since its copy constructor,
+ // copy assignment operator, and destructor are all trivial.
+ return true;
+ }
+
+ };
+
+}
+
+#endif
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index a5b34527969b..0a7124de3621 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -53,7 +53,10 @@ namespace {
void mangleCXXVtable(const CXXRecordDecl *RD);
void mangleCXXVTT(const CXXRecordDecl *RD);
+ void mangleCXXCtorVtable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type);
void mangleCXXRtti(QualType Ty);
+ void mangleCXXRttiName(QualType Ty);
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type);
@@ -65,6 +68,8 @@ namespace {
bool mangleStandardSubstitution(const NamedDecl *ND);
void addSubstitution(const NamedDecl *ND) {
+ ND = cast<NamedDecl>(ND->getCanonicalDecl());
+
addSubstitution(reinterpret_cast<uintptr_t>(ND));
}
void addSubstitution(QualType T);
@@ -127,8 +132,10 @@ static bool isInCLinkageSpecification(const Decl *D) {
bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
// Clang's "overloadable" attribute extension to C/C++ implies name mangling
- // (always).
- if (!FD->hasAttr<OverloadableAttr>()) {
+ // (always) as does passing a C++ member function and a function
+ // whose name is not a simple identifier.
+ if (!FD->hasAttr<OverloadableAttr>() && !isa<CXXMethodDecl>(FD) &&
+ FD->getDeclName().isIdentifier()) {
// C functions are not mangled, and "main" is never mangled.
if (!Context.getASTContext().getLangOptions().CPlusPlus || FD->isMain())
return false;
@@ -140,7 +147,7 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
return false;
// No name mangling in a C linkage specification.
- if (!isa<CXXMethodDecl>(FD) && isInCLinkageSpecification(FD))
+ if (isInCLinkageSpecification(FD))
return false;
}
@@ -212,6 +219,17 @@ void CXXNameMangler::mangleCXXVTT(const CXXRecordDecl *RD) {
mangleName(RD);
}
+void CXXNameMangler::mangleCXXCtorVtable(const CXXRecordDecl *RD,
+ int64_t Offset,
+ const CXXRecordDecl *Type) {
+ // <special-name> ::= TC <type> <offset number> _ <base type>
+ Out << "_ZTC";
+ mangleName(RD);
+ Out << Offset;
+ Out << "_";
+ mangleName(Type);
+}
+
void CXXNameMangler::mangleCXXRtti(QualType Ty) {
// <special-name> ::= TI <type> # typeinfo structure
Out << "_ZTI";
@@ -219,6 +237,13 @@ void CXXNameMangler::mangleCXXRtti(QualType Ty) {
mangleType(Ty);
}
+void CXXNameMangler::mangleCXXRttiName(QualType Ty) {
+ // <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
+ Out << "_ZTS";
+
+ mangleType(Ty);
+}
+
void CXXNameMangler::mangleGuardVariable(const VarDecl *D) {
// <special-name> ::= GV <object name> # Guard variable for one-time
// # initialization
@@ -719,15 +744,15 @@ void CXXNameMangler::mangleType(QualType T) {
// Only operate on the canonical type!
T = Context.getASTContext().getCanonicalType(T);
- bool IsSubstitutable = T.hasQualifiers() || !isa<BuiltinType>(T);
+ bool IsSubstitutable = T.hasLocalQualifiers() || !isa<BuiltinType>(T);
if (IsSubstitutable && mangleSubstitution(T))
return;
- if (Qualifiers Quals = T.getQualifiers()) {
+ if (Qualifiers Quals = T.getLocalQualifiers()) {
mangleQualifiers(Quals);
// Recurse: even if the qualified type isn't yet substitutable,
// the unqualified type might be.
- mangleType(T.getUnqualifiedType());
+ mangleType(T.getLocalUnqualifiedType());
} else {
switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
@@ -1015,6 +1040,11 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
// ::= <expr-primary>
switch (E->getStmtClass()) {
default: assert(false && "Unhandled expression kind!");
+
+ case Expr::ParenExprClass:
+ mangleExpression(cast<ParenExpr>(E)->getSubExpr());
+ break;
+
case Expr::DeclRefExprClass: {
const Decl *D = cast<DeclRefExpr>(E)->getDecl();
@@ -1169,6 +1199,7 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
if (mangleStandardSubstitution(ND))
return true;
+ ND = cast<NamedDecl>(ND->getCanonicalDecl());
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
}
@@ -1255,6 +1286,8 @@ static bool isCharSpecialization(QualType T, const char *Name) {
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
// <substitution> ::= St # ::std::
+ // FIXME: type_info == comes out as __ZNK3std9type_infoeqERKS0_ instead of
+ // __ZNKSt9type_infoeqERKS_
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (isStdNamespace(NS)) {
Out << "St";
@@ -1433,6 +1466,23 @@ namespace clang {
os.flush();
}
+ void mangleCXXVTT(MangleContext &Context, const CXXRecordDecl *RD,
+ llvm::raw_ostream &os) {
+ CXXNameMangler Mangler(Context, os);
+ Mangler.mangleCXXVTT(RD);
+
+ os.flush();
+ }
+
+ void mangleCXXCtorVtable(MangleContext &Context, const CXXRecordDecl *RD,
+ int64_t Offset, const CXXRecordDecl *Type,
+ llvm::raw_ostream &os) {
+ CXXNameMangler Mangler(Context, os);
+ Mangler.mangleCXXCtorVtable(RD, Offset, Type);
+
+ os.flush();
+ }
+
void mangleCXXRtti(MangleContext &Context, QualType Ty,
llvm::raw_ostream &os) {
CXXNameMangler Mangler(Context, os);
@@ -1440,4 +1490,12 @@ namespace clang {
os.flush();
}
+
+ void mangleCXXRttiName(MangleContext &Context, QualType Ty,
+ llvm::raw_ostream &os) {
+ CXXNameMangler Mangler(Context, os);
+ Mangler.mangleCXXRttiName(Ty);
+
+ os.flush();
+ }
}
diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h
index 7f46a106f32a..458708fca6ad 100644
--- a/lib/CodeGen/Mangle.h
+++ b/lib/CodeGen/Mangle.h
@@ -67,8 +67,13 @@ namespace clang {
llvm::raw_ostream &os);
void mangleCXXVTT(MangleContext &Context, const CXXRecordDecl *RD,
llvm::raw_ostream &os);
+ void mangleCXXCtorVtable(MangleContext &Context, const CXXRecordDecl *RD,
+ int64_t Offset, const CXXRecordDecl *Type,
+ llvm::raw_ostream &os);
void mangleCXXRtti(MangleContext &Context, QualType T,
llvm::raw_ostream &os);
+ void mangleCXXRttiName(MangleContext &Context, QualType T,
+ llvm::raw_ostream &os);
void mangleCXXCtor(MangleContext &Context, const CXXConstructorDecl *D,
CXXCtorType Type, llvm::raw_ostream &os);
void mangleCXXDtor(MangleContext &Context, const CXXDestructorDecl *D,
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index c8f686a06f50..1d8f31dd9b24 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -13,7 +13,7 @@
#include "clang/CodeGen/ModuleBuilder.h"
#include "CodeGenModule.h"
-#include "clang/Frontend/CompileOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -32,14 +32,14 @@ namespace {
Diagnostic &Diags;
llvm::OwningPtr<const llvm::TargetData> TD;
ASTContext *Ctx;
- const CompileOptions CompileOpts; // Intentionally copied in.
+ const CodeGenOptions CodeGenOpts; // Intentionally copied in.
protected:
llvm::OwningPtr<llvm::Module> M;
llvm::OwningPtr<CodeGen::CodeGenModule> Builder;
public:
CodeGeneratorImpl(Diagnostic &diags, const std::string& ModuleName,
- const CompileOptions &CO, llvm::LLVMContext& C)
- : Diags(diags), CompileOpts(CO), M(new llvm::Module(ModuleName, C)) {}
+ const CodeGenOptions &CGO, llvm::LLVMContext& C)
+ : Diags(diags), CodeGenOpts(CGO), M(new llvm::Module(ModuleName, C)) {}
virtual ~CodeGeneratorImpl() {}
@@ -57,7 +57,7 @@ namespace {
M->setTargetTriple(Ctx->Target.getTriple().getTriple());
M->setDataLayout(Ctx->Target.getTargetDescription());
TD.reset(new llvm::TargetData(Ctx->Target.getTargetDescription()));
- Builder.reset(new CodeGen::CodeGenModule(Context, CompileOpts,
+ Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts,
*M, *TD, Diags));
}
@@ -96,7 +96,7 @@ namespace {
CodeGenerator *clang::CreateLLVMCodeGen(Diagnostic &Diags,
const std::string& ModuleName,
- const CompileOptions &CO,
+ const CodeGenOptions &CGO,
llvm::LLVMContext& C) {
- return new CodeGeneratorImpl(Diags, ModuleName, CO, C);
+ return new CodeGeneratorImpl(Diags, ModuleName, CGO, C);
}
diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp
index 852bba4ef033..ba0bc6668e27 100644
--- a/lib/CodeGen/TargetABIInfo.cpp
+++ b/lib/CodeGen/TargetABIInfo.cpp
@@ -168,8 +168,28 @@ static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) {
return Size == 32 || Size == 64;
}
-static bool areAllFields32Or64BitBasicType(const RecordDecl *RD,
- ASTContext &Context) {
+/// 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;
@@ -442,14 +462,13 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
if (Ty->isStructureType() && Context.getTypeSize(Ty) == 0)
return ABIArgInfo::getIgnore();
- // Expand structs with size <= 128-bits which consist only of
- // basic types (int, long long, float, double, xxx*). This is
- // non-recursive and does not ignore empty fields.
- if (const RecordType *RT = Ty->getAsStructureType()) {
- if (Context.getTypeSize(Ty) <= 4*32 &&
- areAllFields32Or64BitBasicType(RT->getDecl(), Context))
- return ABIArgInfo::getExpand();
- }
+ // 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 {
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 6088d9617cf0..fcd96f1e5c8c 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -137,7 +137,20 @@ public:
virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
virtual bool IsMathErrnoDefault() const;
+ virtual bool IsBlocksDefault() const {
+ // Blocks default to on for 10.6 (darwin10) and beyond.
+ return (DarwinVersion[0] > 9);
+ }
+ virtual bool IsObjCNonFragileABIDefault() const {
+ // Non-fragile ABI default to on for 10.5 (darwin9) and beyond on x86-64.
+ return (DarwinVersion[0] >= 9 &&
+ getTriple().getArch() == llvm::Triple::x86_64);
+ }
virtual bool IsUnwindTablesDefault() const;
+ virtual unsigned GetDefaultStackProtectorLevel() const {
+ // Stack protectors default to on for 10.6 (darwin10) and beyond.
+ return (DarwinVersion[0] > 9) ? 1 : 0;
+ }
virtual const char *GetDefaultRelocationModel() const;
virtual const char *GetForcedPicModel() const;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 808c31c64828..34154f3a3dce 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -26,6 +26,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Host.h"
#include "llvm/System/Process.h"
#include "InputInfo.h"
@@ -320,6 +321,23 @@ static std::string getLLVMTriple(const ToolChain &TC, const ArgList &Args) {
}
}
+// FIXME: Move to target hook.
+static bool isSignedCharDefault(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ default:
+ return true;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ if (Triple.getOS() == llvm::Triple::Darwin)
+ return true;
+ return false;
+
+ case llvm::Triple::systemz:
+ return false;
+ }
+}
+
void Clang::AddARMTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getHost().getDriver();
@@ -428,28 +446,42 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
false))
CmdArgs.push_back("--no-implicit-float");
+ const char *CPUName = 0;
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- // FIXME: We may need some translation here from the options gcc takes to
- // names the LLVM backend understand?
- CmdArgs.push_back("-mcpu");
- CmdArgs.push_back(A->getValue(Args));
- } else {
- // Select default CPU.
+ if (llvm::StringRef(A->getValue(Args)) == "native") {
+ // FIXME: Reject attempts to use -march=native unless the target matches
+ // the host.
+ //
+ // FIXME: We should also incorporate the detected target features for use
+ // with -native.
+ std::string CPU = llvm::sys::getHostCPUName();
+ if (!CPU.empty())
+ CPUName = Args.MakeArgString(CPU);
+ } else
+ CPUName = A->getValue(Args);
+ }
+ // Select the default CPU if none was given (or detection failed).
+ if (!CPUName) {
// FIXME: Need target hooks.
if (memcmp(getToolChain().getOS().c_str(), "darwin", 6) == 0) {
if (getToolChain().getArchName() == "x86_64")
- CmdArgs.push_back("--mcpu=core2");
+ CPUName = "core2";
else if (getToolChain().getArchName() == "i386")
- CmdArgs.push_back("--mcpu=yonah");
+ CPUName = "yonah";
} else {
if (getToolChain().getArchName() == "x86_64")
- CmdArgs.push_back("--mcpu=x86-64");
+ CPUName = "x86-64";
else if (getToolChain().getArchName() == "i386")
- CmdArgs.push_back("--mcpu=pentium4");
+ CPUName = "pentium4";
}
}
+ if (CPUName) {
+ CmdArgs.push_back("--mcpu");
+ CmdArgs.push_back(CPUName);
+ }
+
// FIXME: Use iterator.
for (ArgList::const_iterator
it = Args.begin(), ie = Args.end(); it != ie; ++it) {
@@ -855,18 +887,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_ffreestanding);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
- Args.AddLastArg(CmdArgs, options::OPT_fgnu_runtime);
Args.AddLastArg(CmdArgs, options::OPT_flax_vector_conversions);
- Args.AddLastArg(CmdArgs, options::OPT_fms_extensions);
- Args.AddLastArg(CmdArgs, options::OPT_fnext_runtime);
Args.AddLastArg(CmdArgs, options::OPT_fno_caret_diagnostics);
Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
Args.AddLastArg(CmdArgs, options::OPT_fobjc_gc_only);
Args.AddLastArg(CmdArgs, options::OPT_fobjc_gc);
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
- // FIXME: Should we remove this?
- Args.AddLastArg(CmdArgs, options::OPT_fobjc_nonfragile_abi);
- Args.AddLastArg(CmdArgs, options::OPT_fobjc_tight_layout);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
@@ -875,32 +901,34 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_pthread);
- // Forward stack protector flags.
+ // -stack-protector=0 is default.
+ unsigned StackProtectorLevel = 0;
if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
options::OPT_fstack_protector_all,
options::OPT_fstack_protector)) {
- if (A->getOption().matches(options::OPT_fno_stack_protector))
- CmdArgs.push_back("--stack-protector=0");
- else if (A->getOption().matches(options::OPT_fstack_protector))
- CmdArgs.push_back("--stack-protector=1");
- else
- CmdArgs.push_back("--stack-protector=2");
+ if (A->getOption().matches(options::OPT_fstack_protector))
+ StackProtectorLevel = 1;
+ else if (A->getOption().matches(options::OPT_fstack_protector_all))
+ StackProtectorLevel = 2;
+ } else
+ StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel();
+ if (StackProtectorLevel) {
+ CmdArgs.push_back("-stack-protector");
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine(StackProtectorLevel)));
}
// Forward -f options with positive and negative forms; we translate
// these by hand.
- // -fbuiltin is default, only pass non-default.
+ // -fbuiltin is default.
if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
CmdArgs.push_back("-fbuiltin=0");
- // -fblocks default varies depending on platform and language; only
- // pass if specified.
- if (Arg *A = Args.getLastArg(options::OPT_fblocks, options::OPT_fno_blocks)) {
- if (A->getOption().matches(options::OPT_fblocks))
- CmdArgs.push_back("-fblocks");
- else
- CmdArgs.push_back("-fblocks=0");
+ // -fblocks=0 is default.
+ if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
+ getToolChain().IsBlocksDefault())) {
+ Args.AddLastArg(CmdArgs, options::OPT_fblock_introspection);
+ CmdArgs.push_back("-fblocks");
}
if (needsExceptions(Args, InputType, getToolChain().getTriple()))
@@ -908,18 +936,40 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-fexceptions=0");
- // -frtti is default, only pass non-default.
+ // -frtti is default.
if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti))
CmdArgs.push_back("-frtti=0");
- // -fsigned-char/-funsigned-char default varies depending on platform; only
+ // -fsigned-char is default.
+ if (!Args.hasFlag(options::OPT_fsigned_char,
+ options::OPT_funsigned_char,
+ isSignedCharDefault(getToolChain().getTriple())))
+ CmdArgs.push_back("-fsigned-char=0");
+
+ // -fms-extensions=0 is default.
+ if (Args.hasFlag(options::OPT_fms_extensions,
+ options::OPT_fno_ms_extensions,
+ getToolChain().getTriple().getOS() == llvm::Triple::Win32))
+ CmdArgs.push_back("-fms-extensions");
+
+ // -fnext-runtime is default.
+ if (!Args.hasFlag(options::OPT_fnext_runtime,
+ options::OPT_fgnu_runtime,
+ getToolChain().getTriple().getOS() == llvm::Triple::Darwin))
+ CmdArgs.push_back("-fgnu-runtime");
+
+ // -fobjc-nonfragile-abi=0 is default.
+ if (types::isObjC(InputType)) {
+ if (Args.hasArg(options::OPT_fobjc_nonfragile_abi) ||
+ getToolChain().IsObjCNonFragileABIDefault())
+ CmdArgs.push_back("-fobjc-nonfragile-abi");
+ }
+
+ // -fshort-wchar default varies depending on platform; only
// pass if specified.
- if (Arg *A = Args.getLastArg(options::OPT_fsigned_char,
- options::OPT_funsigned_char)) {
- if (A->getOption().matches(options::OPT_fsigned_char))
- CmdArgs.push_back("-fsigned-char");
- else
- CmdArgs.push_back("-fsigned-char=0");
+ if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar)) {
+ if (A->getOption().matches(options::OPT_fshort_wchar))
+ CmdArgs.push_back("-fshort-wchar");
}
// -fno-pascal-strings is default, only pass non-default. If the tool chain
@@ -2588,6 +2638,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
+ // FIXME: g++ is more complicated here, it tries to put -lstdc++
+ // before -lm, for example.
+ if (D.CCCIsCXX)
+ CmdArgs.push_back("-lstdc++");
}
const char *Exec =
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index c616c6a5bf4b..30893e7cc0cc 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -89,6 +89,19 @@ bool types::isAcceptedByClang(ID Id) {
}
}
+bool types::isObjC(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_ObjC: case TY_PP_ObjC:
+ case TY_ObjCXX: case TY_PP_ObjCXX:
+ case TY_ObjCHeader: case TY_PP_ObjCHeader:
+ case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+ return true;
+ }
+}
+
bool types::isCXX(ID Id) {
switch (Id) {
default:
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index c0415bf550f8..e3cd6ddd08d6 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Compiler.h"
@@ -61,14 +62,14 @@ public:
return false;
}
- virtual bool ReadTargetTriple(const std::string &Triple) {
+ virtual bool ReadTargetTriple(llvm::StringRef Triple) {
TargetTriple = Triple;
return false;
}
- virtual bool ReadPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+ virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID,
+ llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
Predefines = PCHPredef;
return false;
@@ -132,7 +133,14 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
// PCH loaded successfully. Now create the preprocessor.
// Get information about the target being compiled for.
- AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple));
+ //
+ // FIXME: This is broken, we should store the TargetOptions in the PCH.
+ TargetOptions TargetOpts;
+ TargetOpts.ABI = "";
+ TargetOpts.CPU = "";
+ TargetOpts.Features.clear();
+ TargetOpts.Triple = TargetTriple;
+ AST->Target.reset(TargetInfo::CreateTargetInfo(AST->Diags, TargetOpts));
AST->PP.reset(new Preprocessor(AST->Diags, LangInfo, *AST->Target.get(),
AST->getSourceManager(), HeaderInfo));
Preprocessor &PP = *AST->PP.get();
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index d2831fae566a..ede3d474c848 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -20,6 +20,7 @@
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/LocalCheckers.h"
+#include "clang/Analysis/ManagerRegistry.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/AnalysisManager.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
@@ -27,7 +28,6 @@
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Frontend/ManagerRegistry.h"
#include "clang/Frontend/PathDiagnosticClients.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/Compiler.h"
@@ -44,10 +44,6 @@ static ExplodedNode::Auditor* CreateUbiViz();
// Basic type definitions.
//===----------------------------------------------------------------------===//
-namespace {
- typedef void (*CodeAction)(AnalysisManager& Mgr, Decl *D);
-} // end anonymous namespace
-
//===----------------------------------------------------------------------===//
// Special PathDiagnosticClients.
//===----------------------------------------------------------------------===//
@@ -66,116 +62,135 @@ CreatePlistHTMLDiagnosticClient(const std::string& prefix,
namespace {
- class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
- typedef std::vector<CodeAction> Actions;
- Actions FunctionActions;
- Actions ObjCMethodActions;
- Actions ObjCImplementationActions;
- Actions TranslationUnitActions;
+ class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
+ public:
+ typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
+
+ private:
+ typedef std::vector<CodeAction> Actions;
+ Actions FunctionActions;
+ Actions ObjCMethodActions;
+ Actions ObjCImplementationActions;
+ Actions TranslationUnitActions;
- public:
- ASTContext* Ctx;
- const Preprocessor &PP;
- const std::string OutDir;
- AnalyzerOptions Opts;
+public:
+ ASTContext* Ctx;
+ const Preprocessor &PP;
+ const std::string OutDir;
+ AnalyzerOptions Opts;
+ bool declDisplayed;
- // PD is owned by AnalysisManager.
- PathDiagnosticClient *PD;
+ // PD is owned by AnalysisManager.
+ PathDiagnosticClient *PD;
- StoreManagerCreator CreateStoreMgr;
- ConstraintManagerCreator CreateConstraintMgr;
+ StoreManagerCreator CreateStoreMgr;
+ ConstraintManagerCreator CreateConstraintMgr;
- llvm::OwningPtr<AnalysisManager> Mgr;
+ llvm::OwningPtr<AnalysisManager> Mgr;
- AnalysisConsumer(const Preprocessor& pp,
- const std::string& outdir,
- const AnalyzerOptions& opts)
- : Ctx(0), PP(pp), OutDir(outdir),
- Opts(opts), PD(0) {
- DigestAnalyzerOptions();
- }
+ AnalysisConsumer(const Preprocessor& pp,
+ const std::string& outdir,
+ const AnalyzerOptions& opts)
+ : Ctx(0), PP(pp), OutDir(outdir),
+ Opts(opts), declDisplayed(false), PD(0) {
+ DigestAnalyzerOptions();
+ }
- void DigestAnalyzerOptions() {
- // Create the PathDiagnosticClient.
- if (!OutDir.empty()) {
- switch (Opts.AnalysisDiagOpt) {
- default:
+ void DigestAnalyzerOptions() {
+ // Create the PathDiagnosticClient.
+ if (!OutDir.empty()) {
+ switch (Opts.AnalysisDiagOpt) {
+ default:
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
- case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
+ case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
#include "clang/Frontend/Analyses.def"
- }
}
+ }
- // Create the analyzer component creators.
- if (ManagerRegistry::StoreMgrCreator != 0) {
- CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
- }
- else {
- switch (Opts.AnalysisStoreOpt) {
- default:
- assert(0 && "Unknown store manager.");
+ // Create the analyzer component creators.
+ if (ManagerRegistry::StoreMgrCreator != 0) {
+ CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
+ }
+ else {
+ switch (Opts.AnalysisStoreOpt) {
+ default:
+ assert(0 && "Unknown store manager.");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
- case NAME##Model: CreateStoreMgr = CREATEFN; break;
+ case NAME##Model: CreateStoreMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
- }
}
+ }
- if (ManagerRegistry::ConstraintMgrCreator != 0)
- CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
- else {
- switch (Opts.AnalysisConstraintsOpt) {
- default:
- assert(0 && "Unknown store manager.");
+ if (ManagerRegistry::ConstraintMgrCreator != 0)
+ CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
+ else {
+ switch (Opts.AnalysisConstraintsOpt) {
+ default:
+ assert(0 && "Unknown store manager.");
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
- case NAME##Model: CreateConstraintMgr = CREATEFN; break;
+ case NAME##Model: CreateConstraintMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
- }
}
}
-
- void addCodeAction(CodeAction action) {
- FunctionActions.push_back(action);
- ObjCMethodActions.push_back(action);
- }
-
- void addObjCImplementationAction(CodeAction action) {
- ObjCImplementationActions.push_back(action);
- }
-
- void addTranslationUnitAction(CodeAction action) {
- TranslationUnitActions.push_back(action);
+ }
+
+ void DisplayFunction(const Decl *D) {
+ if (!Opts.AnalyzerDisplayProgress || declDisplayed)
+ return;
+
+ declDisplayed = true;
+ // FIXME: Is getCodeDecl() always a named decl?
+ if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
+ const NamedDecl *ND = cast<NamedDecl>(D);
+ SourceManager &SM = Mgr->getASTContext().getSourceManager();
+ llvm::errs() << "ANALYZE: "
+ << SM.getPresumedLoc(ND->getLocation()).getFilename()
+ << ' ' << ND->getNameAsString() << '\n';
}
+ }
- virtual void Initialize(ASTContext &Context) {
- Ctx = &Context;
- Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
- PP.getLangOptions(), PD,
- CreateStoreMgr, CreateConstraintMgr,
- Opts.AnalyzerDisplayProgress,
- Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
- Opts.PurgeDead, Opts.EagerlyAssume,
- Opts.TrimGraph));
- }
+ void addCodeAction(CodeAction action) {
+ FunctionActions.push_back(action);
+ ObjCMethodActions.push_back(action);
+ }
- virtual void HandleTopLevelDecl(DeclGroupRef D) {
- for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
- HandleTopLevelSingleDecl(*I);
- }
+ void addObjCImplementationAction(CodeAction action) {
+ ObjCImplementationActions.push_back(action);
+ }
- void HandleTopLevelSingleDecl(Decl *D);
- virtual void HandleTranslationUnit(ASTContext &C);
+ void addTranslationUnitAction(CodeAction action) {
+ TranslationUnitActions.push_back(action);
+ }
- void HandleCode(Decl* D, Stmt* Body, Actions& actions);
- };
+ virtual void Initialize(ASTContext &Context) {
+ Ctx = &Context;
+ Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
+ PP.getLangOptions(), PD,
+ CreateStoreMgr, CreateConstraintMgr,
+ Opts.AnalyzerDisplayProgress,
+ Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
+ Opts.PurgeDead, Opts.EagerlyAssume,
+ Opts.TrimGraph));
+ }
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ declDisplayed = false;
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+ void HandleTopLevelSingleDecl(Decl *D);
+ virtual void HandleTranslationUnit(ASTContext &C);
+ void HandleCode(Decl* D, Stmt* Body, Actions& actions);
+};
} // end anonymous namespace
namespace llvm {
- template <> struct FoldingSetTrait<CodeAction> {
- static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
+ template <> struct FoldingSetTrait<AnalysisConsumer::CodeAction> {
+ static inline void Profile(AnalysisConsumer::CodeAction X,
+ FoldingSetNodeID& ID) {
ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
}
};
@@ -238,7 +253,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
for (Actions::iterator I = TranslationUnitActions.begin(),
E = TranslationUnitActions.end(); I != E; ++I)
- (*I)(*Mgr, FD);
+ (*I)(*this, *Mgr, FD);
}
if (!ObjCImplementationActions.empty()) {
@@ -272,34 +287,38 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Dispatch on the actions.
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
- (*I)(*Mgr, D);
+ (*I)(*this, *Mgr, D);
}
//===----------------------------------------------------------------------===//
// Analyses
//===----------------------------------------------------------------------===//
-static void ActionWarnDeadStores(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
if (LiveVariables *L = mgr.getLiveVariables(D)) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
}
}
-static void ActionWarnUninitVals(AnalysisManager& mgr, Decl *D) {
- if (CFG* c = mgr.getCFG(D))
+static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+ if (CFG* c = mgr.getCFG(D)) {
+ C.DisplayFunction(D);
CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
+ }
}
-static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
+static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D,
GRTransferFuncs* tf) {
-
llvm::OwningPtr<GRTransferFuncs> TF(tf);
// Display progress.
- mgr.DisplayFunction(D);
+ C.DisplayFunction(D);
// Construct the analysis engine. We first query for the LiveVariables
// information to see if the CFG is valid.
@@ -312,8 +331,14 @@ static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
Eng.setTransferFunctions(tf);
Eng.RegisterInternalChecks(); // FIXME: Internal checks should just
// automatically register.
+
+ if (C.Opts.EnableExperimentalInternalChecks)
+ RegisterExperimentalInternalChecks(Eng);
+
RegisterAppleChecks(Eng, *D);
-
+
+ if (C.Opts.EnableExperimentalChecks)
+ RegisterExperimentalChecks(Eng);
// Set the graph auditor.
llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
@@ -337,85 +362,103 @@ static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
Eng.getBugReporter().FlushReports();
}
-static void ActionCheckerCFRefAux(AnalysisManager& mgr, Decl *D,
- bool GCEnabled) {
+static void ActionCheckerCFRefAux(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D, bool GCEnabled) {
GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
GCEnabled,
mgr.getLangOptions());
- ActionGRExprEngine(mgr, D, TF);
+ ActionGRExprEngine(C, mgr, D, TF);
}
-static void ActionCheckerCFRef(AnalysisManager& mgr, Decl *D) {
+static void ActionCheckerCFRef(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
switch (mgr.getLangOptions().getGCMode()) {
default:
assert (false && "Invalid GC mode.");
case LangOptions::NonGC:
- ActionCheckerCFRefAux(mgr, D, false);
+ ActionCheckerCFRefAux(C, mgr, D, false);
break;
case LangOptions::GCOnly:
- ActionCheckerCFRefAux(mgr, D, true);
+ ActionCheckerCFRefAux(C, mgr, D, true);
break;
case LangOptions::HybridGC:
- ActionCheckerCFRefAux(mgr, D, false);
- ActionCheckerCFRefAux(mgr, D, true);
+ ActionCheckerCFRefAux(C, mgr, D, false);
+ ActionCheckerCFRefAux(C, mgr, D, true);
break;
}
}
-static void ActionDisplayLiveVariables(AnalysisManager& mgr, Decl *D) {
+static void ActionDisplayLiveVariables(AnalysisConsumer &C,
+ AnalysisManager& mgr, Decl *D) {
if (LiveVariables* L = mgr.getLiveVariables(D)) {
- mgr.DisplayFunction(D);
+ C.DisplayFunction(D);
L->dumpBlockLiveness(mgr.getSourceManager());
}
}
-static void ActionCFGDump(AnalysisManager& mgr, Decl *D) {
- if (CFG* c = mgr.getCFG(D)) {
- mgr.DisplayFunction(D);
- c->dump(mgr.getLangOptions());
+static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
+ if (CFG *cfg = mgr.getCFG(D)) {
+ C.DisplayFunction(D);
+ cfg->dump(mgr.getLangOptions());
}
}
-static void ActionCFGView(AnalysisManager& mgr, Decl *D) {
- if (CFG* c = mgr.getCFG(D)) {
- mgr.DisplayFunction(D);
- c->viewCFG(mgr.getLangOptions());
+static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
+ if (CFG *cfg = mgr.getCFG(D)) {
+ C.DisplayFunction(D);
+ cfg->viewCFG(mgr.getLangOptions());
}
}
-static void ActionSecuritySyntacticChecks(AnalysisManager &mgr, Decl *D) {
+static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
+ AnalysisManager &mgr, Decl *D) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
CheckSecuritySyntaxOnly(D, BR);
}
-static void ActionWarnObjCDealloc(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
return;
+ C.DisplayFunction(D);
BugReporter BR(mgr);
- CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
+ CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
}
-static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
- CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
+ CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
}
-static void ActionWarnObjCMethSigs(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
-
CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
}
-static void ActionInlineCall(AnalysisManager &mgr, Decl *D) {
+static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
+ Decl *D) {
+ C.DisplayFunction(D);
+ BugReporter BR(mgr);
+ CheckSizeofPointer(D, BR);
+}
+
+static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
+ Decl *D) {
if (!D)
return;
+ C.DisplayFunction(D);
llvm::OwningPtr<GRTransferFuncs> TF(CreateCallInliner(mgr.getASTContext()));
// Construct the analysis engine.
diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp
index 13aecf171718..bc56029e73d2 100644
--- a/lib/Frontend/Backend.cpp
+++ b/lib/Frontend/Backend.cpp
@@ -8,12 +8,13 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/ASTConsumers.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Frontend/CompileOptions.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
+#include "clang/CodeGen/ModuleBuilder.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
@@ -40,7 +41,8 @@ using namespace llvm;
namespace {
class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
BackendAction Action;
- CompileOptions CompileOpts;
+ CodeGenOptions CodeGenOpts;
+ TargetOptions TargetOpts;
llvm::raw_ostream *AsmOutStream;
llvm::formatted_raw_ostream FormattedOutStream;
ASTContext *Context;
@@ -75,11 +77,12 @@ namespace {
public:
BackendConsumer(BackendAction action, Diagnostic &Diags,
- const LangOptions &langopts, const CompileOptions &compopts,
- const std::string &infile, llvm::raw_ostream* OS,
- LLVMContext& C) :
+ const LangOptions &langopts, const CodeGenOptions &compopts,
+ const TargetOptions &targetopts, const std::string &infile,
+ llvm::raw_ostream* OS, LLVMContext& C) :
Action(action),
- CompileOpts(compopts),
+ CodeGenOpts(compopts),
+ TargetOpts(targetopts),
AsmOutStream(OS),
LLVMIRGeneration("LLVM IR Generation Time"),
CodeGenerationTime("Code Generation Time"),
@@ -92,7 +95,7 @@ namespace {
formatted_raw_ostream::PRESERVE_STREAM);
// Enable -time-passes if -ftime-report is enabled.
- llvm::TimePassesIsEnabled = CompileOpts.TimePasses;
+ llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
}
~BackendConsumer() {
@@ -106,7 +109,7 @@ namespace {
virtual void Initialize(ASTContext &Ctx) {
Context = &Ctx;
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.startTimer();
Gen->Initialize(Ctx);
@@ -115,7 +118,7 @@ namespace {
ModuleProvider = new ExistingModuleProvider(TheModule);
TheTargetData = new llvm::TargetData(Ctx.Target.getTargetDescription());
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.stopTimer();
}
@@ -124,24 +127,24 @@ namespace {
Context->getSourceManager(),
"LLVM IR generation of declaration");
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.startTimer();
Gen->HandleTopLevelDecl(D);
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.stopTimer();
}
virtual void HandleTranslationUnit(ASTContext &C) {
{
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.startTimer();
Gen->HandleTranslationUnit(C);
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.stopTimer();
}
@@ -202,7 +205,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
} else if (Action == Backend_EmitLL) {
getPerModulePasses()->add(createPrintModulePass(&FormattedOutStream));
} else {
- bool Fast = CompileOpts.OptimizationLevel == 0;
+ bool Fast = CodeGenOpts.OptimizationLevel == 0;
// Create the TargetMachine for generating code.
std::string Triple = TheModule->getTargetTriple();
@@ -213,12 +216,12 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
}
std::string FeaturesStr;
- if (CompileOpts.CPU.size() || CompileOpts.Features.size()) {
+ if (TargetOpts.CPU.size() || TargetOpts.Features.size()) {
SubtargetFeatures Features;
- Features.setCPU(CompileOpts.CPU);
+ Features.setCPU(TargetOpts.CPU);
for (std::vector<std::string>::iterator
- it = CompileOpts.Features.begin(),
- ie = CompileOpts.Features.end(); it != ie; ++it)
+ it = TargetOpts.Features.begin(),
+ ie = TargetOpts.Features.end(); it != ie; ++it)
Features.AddFeature(*it);
FeaturesStr = Features.getString();
}
@@ -237,7 +240,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
FunctionPassManager *PM = getCodeGenPasses();
CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
- switch (CompileOpts.OptimizationLevel) {
+ switch (CodeGenOpts.OptimizationLevel) {
default: break;
case 0: OptLevel = CodeGenOpt::None; break;
case 3: OptLevel = CodeGenOpt::Aggressive; break;
@@ -266,37 +269,44 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
}
void BackendConsumer::CreatePasses() {
+ unsigned OptLevel = CodeGenOpts.OptimizationLevel;
+ CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining;
+
+ // Handle disabling of LLVM optimization, where we want to preserve the
+ // internal module before any optimization.
+ if (CodeGenOpts.DisableLLVMOpts) {
+ OptLevel = 0;
+ Inlining = CodeGenOpts.NoInlining;
+ }
+
// In -O0 if checking is disabled, we don't even have per-function passes.
- if (CompileOpts.VerifyModule)
+ if (CodeGenOpts.VerifyModule)
getPerFunctionPasses()->add(createVerifierPass());
// Assume that standard function passes aren't run for -O0.
- if (CompileOpts.OptimizationLevel > 0)
- llvm::createStandardFunctionPasses(getPerFunctionPasses(),
- CompileOpts.OptimizationLevel);
+ if (OptLevel > 0)
+ llvm::createStandardFunctionPasses(getPerFunctionPasses(), OptLevel);
llvm::Pass *InliningPass = 0;
- switch (CompileOpts.Inlining) {
- case CompileOptions::NoInlining: break;
- case CompileOptions::NormalInlining: {
+ switch (Inlining) {
+ case CodeGenOptions::NoInlining: break;
+ case CodeGenOptions::NormalInlining: {
// Inline small functions
- unsigned Threshold = (CompileOpts.OptimizeSize ||
- CompileOpts.OptimizationLevel < 3) ? 50 : 200;
+ unsigned Threshold = (CodeGenOpts.OptimizeSize || OptLevel < 3) ? 50 : 200;
InliningPass = createFunctionInliningPass(Threshold);
break;
}
- case CompileOptions::OnlyAlwaysInlining:
+ case CodeGenOptions::OnlyAlwaysInlining:
InliningPass = createAlwaysInlinerPass(); // Respect always_inline
break;
}
// For now we always create per module passes.
PassManager *PM = getPerModulePasses();
- llvm::createStandardModulePasses(PM, CompileOpts.OptimizationLevel,
- CompileOpts.OptimizeSize,
- CompileOpts.UnitAtATime,
- CompileOpts.UnrollLoops,
- CompileOpts.SimplifyLibCalls,
+ llvm::createStandardModulePasses(PM, OptLevel, CodeGenOpts.OptimizeSize,
+ CodeGenOpts.UnitAtATime,
+ CodeGenOpts.UnrollLoops,
+ CodeGenOpts.SimplifyLibCalls,
/*HaveExceptions=*/true,
InliningPass);
}
@@ -308,7 +318,7 @@ void BackendConsumer::EmitAssembly() {
if (!TheModule || !TheTargetData)
return;
- TimeRegion Region(CompileOpts.TimePasses ? &CodeGenerationTime : 0);
+ TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : 0);
// Make sure IR generation is happy with the module. This is
// released by the module provider.
@@ -363,10 +373,11 @@ void BackendConsumer::EmitAssembly() {
ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &LangOpts,
- const CompileOptions &CompileOpts,
+ const CodeGenOptions &CodeGenOpts,
+ const TargetOptions &TargetOpts,
const std::string& InFile,
llvm::raw_ostream* OS,
LLVMContext& C) {
- return new BackendConsumer(Action, Diags, LangOpts, CompileOpts,
- InFile, OS, C);
+ return new BackendConsumer(Action, Diags, LangOpts, CodeGenOpts,
+ TargetOpts, InFile, OS, C);
}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index e3ec78627da0..3f0f43099c69 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -6,17 +6,21 @@ add_clang_library(clangFrontend
AnalysisConsumer.cpp
Backend.cpp
CacheTokens.cpp
+ CompilerInstance.cpp
+ CompilerInvocation.cpp
DeclXML.cpp
DependencyFile.cpp
DiagChecker.cpp
DocumentXML.cpp
FixItRewriter.cpp
+ FrontendAction.cpp
+ FrontendActions.cpp
+ FrontendOptions.cpp
GeneratePCH.cpp
HTMLDiagnostics.cpp
HTMLPrint.cpp
InitHeaderSearch.cpp
InitPreprocessor.cpp
- ManagerRegistry.cpp
PCHReader.cpp
PCHReaderDecl.cpp
PCHReaderStmt.cpp
@@ -34,6 +38,7 @@ add_clang_library(clangFrontend
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
TypeXML.cpp
+ VerifyDiagnosticsClient.cpp
Warnings.cpp
)
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
new file mode 100644
index 000000000000..0365761c840e
--- /dev/null
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -0,0 +1,403 @@
+//===--- CompilerInstance.cpp ---------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PTHManager.h"
+#include "clang/Frontend/ChainedDiagnosticClient.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+using namespace clang;
+
+CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext,
+ bool _OwnsLLVMContext)
+ : LLVMContext(_LLVMContext),
+ OwnsLLVMContext(_OwnsLLVMContext) {
+ }
+
+CompilerInstance::~CompilerInstance() {
+ if (OwnsLLVMContext)
+ delete LLVMContext;
+}
+
+void CompilerInstance::setDiagnostics(Diagnostic *Value) {
+ Diagnostics.reset(Value);
+}
+
+void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
+ DiagClient.reset(Value);
+}
+
+void CompilerInstance::setTarget(TargetInfo *Value) {
+ Target.reset(Value);
+}
+
+void CompilerInstance::setFileManager(FileManager *Value) {
+ FileMgr.reset(Value);
+}
+
+void CompilerInstance::setSourceManager(SourceManager *Value) {
+ SourceMgr.reset(Value);
+}
+
+void CompilerInstance::setPreprocessor(Preprocessor *Value) {
+ PP.reset(Value);
+}
+
+void CompilerInstance::setASTContext(ASTContext *Value) {
+ Context.reset(Value);
+}
+
+void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
+ Consumer.reset(Value);
+}
+
+void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
+ CompletionConsumer.reset(Value);
+}
+
+// Diagnostics
+
+static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
+ unsigned argc, char **argv,
+ llvm::OwningPtr<DiagnosticClient> &DiagClient) {
+ std::string ErrorInfo;
+ llvm::raw_ostream *OS =
+ new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo);
+ if (!ErrorInfo.empty()) {
+ // FIXME: Do not fail like this.
+ llvm::errs() << "error opening -dump-build-information file '"
+ << DiagOpts.DumpBuildInformation << "', option ignored!\n";
+ delete OS;
+ return;
+ }
+
+ (*OS) << "clang-cc command line arguments: ";
+ for (unsigned i = 0; i != argc; ++i)
+ (*OS) << argv[i] << ' ';
+ (*OS) << '\n';
+
+ // Chain in a diagnostic client which will log the diagnostics.
+ DiagnosticClient *Logger =
+ new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true);
+ DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger));
+}
+
+void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
+ Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
+
+ if (Diagnostics)
+ DiagClient.reset(Diagnostics->getClient());
+}
+
+Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
+ int Argc, char **Argv) {
+ llvm::OwningPtr<Diagnostic> Diags(new Diagnostic());
+
+ // Create the diagnostic client for reporting errors or for
+ // implementing -verify.
+ llvm::OwningPtr<DiagnosticClient> DiagClient(
+ new TextDiagnosticPrinter(llvm::errs(), Opts));
+
+ // Chain in -verify checker, if requested.
+ if (Opts.VerifyDiagnostics)
+ DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
+
+ if (!Opts.DumpBuildInformation.empty())
+ SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient);
+
+ // Configure our handling of diagnostics.
+ Diags->setClient(DiagClient.take());
+ if (ProcessWarningOptions(*Diags, Opts))
+ return 0;
+
+ return Diags.take();
+}
+
+// File Manager
+
+void CompilerInstance::createFileManager() {
+ FileMgr.reset(new FileManager());
+}
+
+// Source Manager
+
+void CompilerInstance::createSourceManager() {
+ SourceMgr.reset(new SourceManager());
+}
+
+// Preprocessor
+
+void CompilerInstance::createPreprocessor() {
+ PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
+ getPreprocessorOpts(), getHeaderSearchOpts(),
+ getDependencyOutputOpts(), getTarget(),
+ getSourceManager(), getFileManager()));
+}
+
+Preprocessor *
+CompilerInstance::createPreprocessor(Diagnostic &Diags,
+ const LangOptions &LangInfo,
+ const PreprocessorOptions &PPOpts,
+ const HeaderSearchOptions &HSOpts,
+ const DependencyOutputOptions &DepOpts,
+ const TargetInfo &Target,
+ SourceManager &SourceMgr,
+ FileManager &FileMgr) {
+ // Create a PTH manager if we are using some form of a token cache.
+ PTHManager *PTHMgr = 0;
+ if (!PPOpts.TokenCache.empty())
+ PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
+
+ // FIXME: Don't fail like this.
+ if (Diags.hasErrorOccurred())
+ exit(1);
+
+ // Create the Preprocessor.
+ HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
+ Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
+ SourceMgr, *HeaderInfo, PTHMgr,
+ /*OwnsHeaderSearch=*/true);
+
+ // Note that this is different then passing PTHMgr to Preprocessor's ctor.
+ // That argument is used as the IdentifierInfoLookup argument to
+ // IdentifierTable's ctor.
+ if (PTHMgr) {
+ PTHMgr->setPreprocessor(PP);
+ PP->setPTHManager(PTHMgr);
+ }
+
+ InitializePreprocessor(*PP, PPOpts, HSOpts);
+
+ // Handle generating dependencies, if requested.
+ if (!DepOpts.OutputFile.empty())
+ AttachDependencyFileGen(*PP, DepOpts);
+
+ return PP;
+}
+
+// ASTContext
+
+void CompilerInstance::createASTContext() {
+ Preprocessor &PP = getPreprocessor();
+ Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
+ getTarget(), PP.getIdentifierTable(),
+ PP.getSelectorTable(), PP.getBuiltinInfo(),
+ /*FreeMemory=*/ !getFrontendOpts().DisableFree,
+ /*size_reserve=*/ 0));
+}
+
+// ExternalASTSource
+
+void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
+ llvm::OwningPtr<ExternalASTSource> Source;
+ Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
+ getPreprocessor(), getASTContext()));
+ getASTContext().setExternalSource(Source);
+}
+
+ExternalASTSource *
+CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
+ const std::string &Sysroot,
+ Preprocessor &PP,
+ ASTContext &Context) {
+ llvm::OwningPtr<PCHReader> Reader;
+ Reader.reset(new PCHReader(PP, &Context,
+ Sysroot.empty() ? 0 : Sysroot.c_str()));
+
+ switch (Reader->ReadPCH(Path)) {
+ case PCHReader::Success:
+ // Set the predefines buffer as suggested by the PCH reader. Typically, the
+ // predefines buffer will be empty.
+ PP.setPredefines(Reader->getSuggestedPredefines());
+ return Reader.take();
+
+ case PCHReader::Failure:
+ // Unrecoverable failure: don't even try to process the input file.
+ break;
+
+ case PCHReader::IgnorePCH:
+ // No suitable PCH file could be found. Return an error.
+ break;
+ }
+
+ return 0;
+}
+
+// Code Completion
+
+void CompilerInstance::createCodeCompletionConsumer() {
+ const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
+ CompletionConsumer.reset(
+ createCodeCompletionConsumer(getPreprocessor(),
+ Loc.FileName, Loc.Line, Loc.Column,
+ getFrontendOpts().DebugCodeCompletionPrinter,
+ getFrontendOpts().ShowMacrosInCodeCompletion,
+ llvm::outs()));
+}
+
+CodeCompleteConsumer *
+CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
+ const std::string &Filename,
+ unsigned Line,
+ unsigned Column,
+ bool UseDebugPrinter,
+ bool ShowMacros,
+ llvm::raw_ostream &OS) {
+ // Tell the source manager to chop off the given file at a specific
+ // line and column.
+ const FileEntry *Entry = PP.getFileManager().getFile(Filename);
+ if (!Entry) {
+ PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
+ << Filename;
+ return 0;
+ }
+
+ // Truncate the named file at the given line/column.
+ PP.getSourceManager().truncateFileAt(Entry, Line, Column);
+
+ // Set up the creation routine for code-completion.
+ if (UseDebugPrinter)
+ return new PrintingCodeCompleteConsumer(ShowMacros, OS);
+ else
+ return new CIndexCodeCompleteConsumer(ShowMacros, OS);
+}
+
+// Output Files
+
+void CompilerInstance::addOutputFile(llvm::StringRef Path,
+ llvm::raw_ostream *OS) {
+ assert(OS && "Attempt to add empty stream to output list!");
+ OutputFiles.push_back(std::make_pair(Path, OS));
+}
+
+void CompilerInstance::ClearOutputFiles(bool EraseFiles) {
+ for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
+ it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
+ delete it->second;
+ if (EraseFiles && !it->first.empty())
+ llvm::sys::Path(it->first).eraseFromDisk();
+ }
+ OutputFiles.clear();
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createDefaultOutputFile(bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ return createOutputFile(getFrontendOpts().OutputFile, Binary,
+ InFile, Extension);
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ std::string Error, OutputPathName;
+ llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
+ InFile, Extension,
+ &OutputPathName);
+ if (!OS) {
+ // FIXME: Don't fail this way.
+ llvm::errs() << "ERROR: " << Error << "\n";
+ ::exit(1);
+ }
+
+ // Add the output file -- but don't try to remove "-", since this means we are
+ // using stdin.
+ addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
+
+ return OS;
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ std::string &Error,
+ bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension,
+ std::string *ResultPathName) {
+ std::string OutFile;
+ if (!OutputPath.empty()) {
+ OutFile = OutputPath;
+ } else if (InFile == "-") {
+ OutFile = "-";
+ } else if (!Extension.empty()) {
+ llvm::sys::Path Path(InFile);
+ Path.eraseSuffix();
+ Path.appendSuffix(Extension);
+ OutFile = Path.str();
+ } else {
+ OutFile = "-";
+ }
+
+ llvm::raw_fd_ostream *OS =
+ new llvm::raw_fd_ostream(OutFile.c_str(), Error,
+ (Binary ? llvm::raw_fd_ostream::F_Binary : 0));
+ if (!OS)
+ return 0;
+
+ if (ResultPathName)
+ *ResultPathName = OutFile;
+
+ return OS;
+}
+
+// Initialization Utilities
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
+ return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
+ getSourceManager(), getFrontendOpts());
+}
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
+ Diagnostic &Diags,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ const FrontendOptions &Opts) {
+ // Figure out where to get and map in the main file.
+ if (Opts.EmptyInputOnly) {
+ const char *EmptyStr = "";
+ llvm::MemoryBuffer *SB =
+ llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
+ SourceMgr.createMainFileIDForMemBuffer(SB);
+ } else if (InputFile != "-") {
+ const FileEntry *File = FileMgr.getFile(InputFile);
+ if (File) SourceMgr.createMainFileID(File, SourceLocation());
+ if (SourceMgr.getMainFileID().isInvalid()) {
+ Diags.Report(diag::err_fe_error_reading) << InputFile;
+ return false;
+ }
+ } else {
+ llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
+ SourceMgr.createMainFileIDForMemBuffer(SB);
+ if (SourceMgr.getMainFileID().isInvalid()) {
+ Diags.Report(diag::err_fe_error_reading_stdin);
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
new file mode 100644
index 000000000000..ed6d0b71a51b
--- /dev/null
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -0,0 +1,548 @@
+//===--- CompilerInvocation.cpp -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInvocation.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
+ const llvm::SmallVectorImpl<llvm::StringRef> &Args) {
+ llvm::llvm_report_error("FIXME: Not yet implemented!");
+}
+
+static const char *getAnalysisName(Analyses Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis store!");
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
+ case NAME: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisStoreName(AnalysisStores Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis store!");
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis constraints!");
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis client!");
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
+ case PD_##NAME: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
+ std::vector<std::string> &Res) {
+ for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i)
+ Res.push_back(getAnalysisName(Opts.AnalysisList[i]));
+ if (Opts.AnalysisStoreOpt != BasicStoreModel) {
+ Res.push_back("-analyzer-store");
+ Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt));
+ }
+ if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
+ Res.push_back("-analyzer-constraints");
+ Res.push_back(getAnalysisConstraintName(Opts.AnalysisConstraintsOpt));
+ }
+ if (Opts.AnalysisDiagOpt != PD_HTML) {
+ Res.push_back("-analyzer-output");
+ Res.push_back(getAnalysisDiagClientName(Opts.AnalysisDiagOpt));
+ }
+ if (!Opts.AnalyzeSpecificFunction.empty()) {
+ Res.push_back("-analyze-function");
+ Res.push_back(Opts.AnalyzeSpecificFunction);
+ }
+ if (Opts.AnalyzeAll)
+ Res.push_back("-analyzer-opt-analyze-headers");
+ if (Opts.AnalyzerDisplayProgress)
+ Res.push_back("-analyzer-display-progress");
+ if (Opts.EagerlyAssume)
+ Res.push_back("-analyzer-eagerly-assume");
+ if (Opts.PurgeDead)
+ Res.push_back("-analyzer-purge-dead");
+ if (Opts.TrimGraph)
+ Res.push_back("-trim-egraph");
+ if (Opts.VisualizeEGDot)
+ Res.push_back("-analyzer-viz-egraph-graphviz");
+ if (Opts.VisualizeEGDot)
+ Res.push_back("-analyzer-viz-egraph-ubigraph");
+ if (Opts.EnableExperimentalChecks)
+ Res.push_back("-analyzer-experimental-checks");
+ if (Opts.EnableExperimentalInternalChecks)
+ Res.push_back("-analyzer-experimental-internal-checls");
+}
+
+static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.DebugInfo)
+ Res.push_back("-g");
+ if (Opts.DisableLLVMOpts)
+ Res.push_back("-disable-llvm-optzns");
+ if (Opts.DisableRedZone)
+ Res.push_back("-disable-red-zone");
+ if (!Opts.MergeAllConstants)
+ Res.push_back("-fno-merge-all-constants");
+ // NoCommon is only derived.
+ if (Opts.NoImplicitFloat)
+ Res.push_back("-no-implicit-float");
+ if (Opts.OptimizeSize) {
+ assert(Opts.OptimizationLevel == 2 && "Invalid options!");
+ Res.push_back("-Os");
+ } else if (Opts.OptimizationLevel == 0)
+ Res.push_back("-O" + Opts.OptimizationLevel);
+ // SimplifyLibCalls is only derived.
+ // TimePasses is only derived.
+ // UnitAtATime is unused.
+ // UnrollLoops is only derived.
+ // VerifyModule is only derived.
+ // Inlining is only derived.
+}
+
+static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.IncludeSystemHeaders)
+ Res.push_back("-sys-header-deps");
+ if (Opts.UsePhonyTargets)
+ Res.push_back("-MP");
+ if (!Opts.OutputFile.empty()) {
+ Res.push_back("-dependency-file");
+ Res.push_back(Opts.OutputFile);
+ }
+ for (unsigned i = 0, e = Opts.Targets.size(); i != e; ++i) {
+ Res.push_back("-MT");
+ Res.push_back(Opts.Targets[i]);
+ }
+}
+
+static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.IgnoreWarnings)
+ Res.push_back("-w");
+ if (Opts.NoRewriteMacros)
+ Res.push_back("-Wno-rewrite-macros");
+ if (Opts.Pedantic)
+ Res.push_back("-pedantic");
+ if (Opts.PedanticErrors)
+ Res.push_back("-pedantic-errors");
+ if (!Opts.ShowColumn)
+ Res.push_back("-fno-show-column");
+ if (!Opts.ShowLocation)
+ Res.push_back("-fno-show-source-location");
+ if (!Opts.ShowCarets)
+ Res.push_back("-fno-caret-diagnostics");
+ if (!Opts.ShowFixits)
+ Res.push_back("-fno-diagnostics-fixit-info");
+ if (Opts.ShowSourceRanges)
+ Res.push_back("-fdiagnostics-print-source-range-info");
+ if (Opts.ShowColors)
+ Res.push_back("-fcolor-diagnostics");
+ if (Opts.VerifyDiagnostics)
+ Res.push_back("-verify");
+ if (Opts.ShowOptionNames)
+ Res.push_back("-fdiagnostics-show-option");
+ if (Opts.MessageLength) {
+ Res.push_back("-fmessage-length");
+ Res.push_back(llvm::utostr(Opts.MessageLength));
+ }
+ if (!Opts.DumpBuildInformation.empty()) {
+ Res.push_back("-dump-build-information");
+ Res.push_back(Opts.DumpBuildInformation);
+ }
+ for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i)
+ Res.push_back("-W" + Opts.Warnings[i]);
+}
+
+static const char *getInputKindName(FrontendOptions::InputKind Kind) {
+ switch (Kind) {
+ case FrontendOptions::IK_None: break;
+ case FrontendOptions::IK_AST: return "ast";
+ case FrontendOptions::IK_Asm: return "assembler-with-cpp";
+ case FrontendOptions::IK_C: return "c";
+ case FrontendOptions::IK_CXX: return "c++";
+ case FrontendOptions::IK_ObjC: return "objective-c";
+ case FrontendOptions::IK_ObjCXX: return "objective-c++";
+ case FrontendOptions::IK_OpenCL: return "cl";
+ case FrontendOptions::IK_PreprocessedC: return "cpp-output";
+ case FrontendOptions::IK_PreprocessedCXX: return "c++-cpp-output";
+ case FrontendOptions::IK_PreprocessedObjC: return "objective-c-cpp-output";
+ case FrontendOptions::IK_PreprocessedObjCXX: return "objective-c++-cpp-output";
+ }
+
+ llvm::llvm_unreachable("Unexpected language kind!");
+ return 0;
+}
+
+static const char *getActionName(frontend::ActionKind Kind) {
+ switch (Kind) {
+ case frontend::PluginAction:
+ case frontend::InheritanceView:
+ llvm::llvm_unreachable("Invalid kind!");
+
+ case frontend::ASTDump: return "-ast-dump";
+ case frontend::ASTPrint: return "-ast-print";
+ case frontend::ASTPrintXML: return "-ast-print-xml";
+ case frontend::ASTView: return "-ast-view";
+ case frontend::DumpRawTokens: return "-dump-raw-tokens";
+ case frontend::DumpRecordLayouts: return "-dump-record-layouts";
+ case frontend::DumpTokens: return "-dump-tokens";
+ case frontend::EmitAssembly: return "-S";
+ case frontend::EmitBC: return "-emit-llvm-bc";
+ case frontend::EmitHTML: return "-emit-html";
+ case frontend::EmitLLVM: return "-emit-llvm";
+ case frontend::EmitLLVMOnly: return "-emit-llvm-only";
+ case frontend::FixIt: return "-fixit";
+ case frontend::GeneratePCH: return "-emit-pch";
+ case frontend::GeneratePTH: return "-emit-pth";
+ case frontend::ParseNoop: return "-parse-noop";
+ case frontend::ParsePrintCallbacks: return "-parse-print-callbacks";
+ case frontend::ParseSyntaxOnly: return "-fsyntax-only";
+ case frontend::PrintDeclContext: return "-print-decl-contexts";
+ case frontend::PrintPreprocessedInput: return "-E";
+ case frontend::RewriteBlocks: return "-rewrite-blocks";
+ case frontend::RewriteMacros: return "-rewrite-macros";
+ case frontend::RewriteObjC: return "-rewrite-objc";
+ case frontend::RewriteTest: return "-rewrite-test";
+ case frontend::RunAnalysis: return "-analyze";
+ case frontend::RunPreprocessorOnly: return "-Eonly";
+ }
+
+ llvm::llvm_unreachable("Unexpected language kind!");
+ return 0;
+}
+
+static void FrontendOptsToArgs(const FrontendOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (!Opts.DebugCodeCompletionPrinter)
+ Res.push_back("-code-completion-debug-printer=0");
+ if (Opts.DisableFree)
+ Res.push_back("-disable-free");
+ if (Opts.EmptyInputOnly)
+ Res.push_back("-empty-input-only");
+ if (Opts.RelocatablePCH)
+ Res.push_back("-relocatable-pch");
+ if (Opts.ShowMacrosInCodeCompletion)
+ Res.push_back("-code-completion-macros");
+ if (Opts.ShowStats)
+ Res.push_back("-stats");
+ if (Opts.ShowTimers)
+ Res.push_back("-ftime-report");
+
+ bool NeedLang = false;
+ for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
+ if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].second) !=
+ Opts.Inputs[i].first)
+ NeedLang = true;
+ if (NeedLang) {
+ Res.push_back("-x");
+ Res.push_back(getInputKindName(Opts.Inputs[0].first));
+ }
+ for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
+ assert((!NeedLang || Opts.Inputs[i].first == Opts.Inputs[0].first) &&
+ "Unable to represent this input vector!");
+ Res.push_back(Opts.Inputs[i].second);
+ }
+
+ if (!Opts.OutputFile.empty()) {
+ Res.push_back("-o");
+ Res.push_back(Opts.OutputFile);
+ }
+ if (!Opts.ViewClassInheritance.empty()) {
+ Res.push_back("-cxx-inheritance-view");
+ Res.push_back(Opts.ViewClassInheritance);
+ }
+ for (unsigned i = 0, e = Opts.FixItLocations.size(); i != e; ++i) {
+ Res.push_back("-fixit-at");
+ Res.push_back(Opts.FixItLocations[i].FileName + ":" +
+ llvm::utostr(Opts.FixItLocations[i].Line) + ":" +
+ llvm::utostr(Opts.FixItLocations[i].Column));
+ }
+ if (!Opts.CodeCompletionAt.FileName.empty()) {
+ Res.push_back("-code-completion-at");
+ Res.push_back(Opts.CodeCompletionAt.FileName + ":" +
+ llvm::utostr(Opts.CodeCompletionAt.Line) + ":" +
+ llvm::utostr(Opts.CodeCompletionAt.Column));
+ }
+ if (Opts.ProgramAction != frontend::InheritanceView &&
+ Opts.ProgramAction != frontend::PluginAction)
+ Res.push_back(getActionName(Opts.ProgramAction));
+ if (!Opts.ActionName.empty()) {
+ Res.push_back("-plugin");
+ Res.push_back(Opts.ActionName);
+ }
+}
+
+static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.Sysroot.empty()) {
+ Res.push_back("-isysroot");
+ Res.push_back(Opts.Sysroot);
+ }
+
+ /// User specified include entries.
+ for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
+ const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
+ if (E.IsFramework && (E.Group != frontend::Angled || E.IsUserSupplied))
+ llvm::llvm_report_error("Invalid option set!");
+ if (E.IsUserSupplied) {
+ if (E.Group == frontend::After) {
+ Res.push_back("-idirafter");
+ } else if (E.Group == frontend::Quoted) {
+ Res.push_back("-iquoted");
+ } else if (E.Group == frontend::System) {
+ Res.push_back("-isystem");
+ } else {
+ assert(E.Group == frontend::Angled && "Invalid group!");
+ Res.push_back(E.IsFramework ? "-F" : "-I");
+ }
+ } else {
+ if (E.Group != frontend::Angled && E.Group != frontend::System)
+ llvm::llvm_report_error("Invalid option set!");
+ Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" :
+ "-iwithprefix");
+ }
+ Res.push_back(E.Path);
+ }
+
+ if (!Opts.EnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.CEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.ObjCEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.CXXEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.ObjCXXEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.BuiltinIncludePath.empty()) {
+ // FIXME: Provide an option for this, and move to driver.
+ }
+ if (!Opts.UseStandardIncludes)
+ Res.push_back("-nostdinc");
+ if (Opts.Verbose)
+ Res.push_back("-v");
+}
+
+static void LangOptsToArgs(const LangOptions &Opts,
+ std::vector<std::string> &Res) {
+ LangOptions DefaultLangOpts;
+
+ // FIXME: Need to set -std to get all the implicit options.
+
+ // FIXME: We want to only pass options relative to the defaults, which
+ // requires constructing a target. :(
+ //
+ // It would be better to push the all target specific choices into the driver,
+ // so that everything below that was more uniform.
+
+ if (Opts.Trigraphs)
+ Res.push_back("-trigraphs");
+ // Implicit based on the input kind:
+ // AsmPreprocessor, CPlusPlus, ObjC1, ObjC2, OpenCL
+ // Implicit based on the input language standard:
+ // BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
+ if (Opts.DollarIdents)
+ Res.push_back("-fdollars-in-identifiers");
+ if (Opts.Microsoft)
+ Res.push_back("-fms-extensions=1");
+ if (Opts.ObjCNonFragileABI)
+ Res.push_back("-fobjc-nonfragile-abi");
+ // NoInline is implicit.
+ if (!Opts.CXXOperatorNames)
+ Res.push_back("-fno-operator-names");
+ if (Opts.PascalStrings)
+ Res.push_back("-fpascal-strings");
+ if (Opts.WritableStrings)
+ Res.push_back("-fwritable-strings");
+ if (!Opts.LaxVectorConversions)
+ Res.push_back("-fno-lax-vector-conversions");
+ if (Opts.AltiVec)
+ Res.push_back("-faltivec");
+ Res.push_back("-fexceptions");
+ Res.push_back(Opts.Exceptions ? "1" : "0");
+ Res.push_back("-frtti");
+ Res.push_back(Opts.Rtti ? "1" : "0");
+ if (!Opts.NeXTRuntime)
+ Res.push_back("-fgnu-runtime");
+ if (Opts.Freestanding)
+ Res.push_back("-ffreestanding");
+ if (Opts.NoBuiltin)
+ Res.push_back("-fno-builtin");
+ if (Opts.ThreadsafeStatics)
+ llvm::llvm_report_error("FIXME: Not yet implemented!");
+ if (Opts.POSIXThreads)
+ Res.push_back("-pthread");
+ if (Opts.Blocks)
+ Res.push_back("-fblocks=1");
+ if (Opts.EmitAllDecls)
+ Res.push_back("-femit-all-decls");
+ if (!Opts.MathErrno)
+ Res.push_back("-fmath-errno=0");
+ if (Opts.OverflowChecking)
+ Res.push_back("-ftrapv");
+ if (Opts.HeinousExtensions)
+ Res.push_back("-fheinous-gnu-extensions");
+ // Optimize is implicit.
+ // OptimizeSize is implicit.
+ if (Opts.Static)
+ Res.push_back("-static-define");
+ if (Opts.PICLevel) {
+ Res.push_back("-pic-level");
+ Res.push_back(llvm::utostr(Opts.PICLevel));
+ }
+ if (Opts.ObjCGCBitmapPrint)
+ Res.push_back("-print-ivar-layout");
+ Res.push_back("-faccess-control");
+ Res.push_back(Opts.AccessControl ? "1" : "0");
+ Res.push_back("-fsigned-char");
+ Res.push_back(Opts.CharIsSigned ? "1" : "0");
+ Res.push_back("-fshort-wchar");
+ Res.push_back(Opts.ShortWChar ? "1" : "0");
+ if (!Opts.ElideConstructors)
+ Res.push_back("-fno-elide-constructors");
+ if (Opts.getGCMode() != LangOptions::NonGC) {
+ if (Opts.getGCMode() == LangOptions::HybridGC) {
+ Res.push_back("-fobjc-gc");
+ } else {
+ assert(Opts.getGCMode() == LangOptions::GCOnly && "Invalid GC mode!");
+ Res.push_back("-fobjc-gc-only");
+ }
+ }
+ if (Opts.getVisibilityMode() != LangOptions::Default) {
+ Res.push_back("-fvisibility");
+ if (Opts.getVisibilityMode() == LangOptions::Hidden) {
+ Res.push_back("default");
+ } else {
+ assert(Opts.getVisibilityMode() == LangOptions::Protected &&
+ "Invalid visibility!");
+ Res.push_back("protected");
+ }
+ }
+ if (Opts.getStackProtectorMode() != 0) {
+ Res.push_back("-stack-protector");
+ Res.push_back(llvm::utostr(Opts.getStackProtectorMode()));
+ }
+ if (Opts.getMainFileName()) {
+ Res.push_back("-main-file-name");
+ Res.push_back(Opts.getMainFileName());
+ }
+ if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth) {
+ Res.push_back("-ftemplate-depth");
+ Res.push_back(llvm::utostr(Opts.InstantiationDepth));
+ }
+ if (Opts.ObjCConstantStringClass) {
+ Res.push_back("-fconstant-string-class");
+ Res.push_back(Opts.ObjCConstantStringClass);
+ }
+}
+
+static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
+ std::vector<std::string> &Res) {
+ for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i)
+ Res.push_back((Opts.Macros[i].second ? "-U" : "-D") + Opts.Macros[i].first);
+ for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) {
+ Res.push_back("-include");
+ Res.push_back(Opts.Includes[i]);
+ }
+ for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i) {
+ Res.push_back("-imacros");
+ Res.push_back(Opts.Includes[i]);
+ }
+ if (!Opts.UsePredefines)
+ Res.push_back("-undef");
+ if (!Opts.ImplicitPCHInclude.empty()) {
+ Res.push_back("-implicit-pch-include");
+ Res.push_back(Opts.ImplicitPCHInclude);
+ }
+ if (!Opts.ImplicitPTHInclude.empty()) {
+ Res.push_back("-implicit-pth-include");
+ Res.push_back(Opts.ImplicitPTHInclude);
+ }
+ if (!Opts.TokenCache.empty()) {
+ Res.push_back("-token-cache");
+ Res.push_back(Opts.TokenCache);
+ }
+}
+
+static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (!Opts.ShowCPP && !Opts.ShowMacros)
+ llvm::llvm_report_error("Invalid option combination!");
+
+ if (Opts.ShowCPP && Opts.ShowMacros)
+ Res.push_back("-dD");
+ else if (!Opts.ShowCPP && Opts.ShowMacros)
+ Res.push_back("-dM");
+
+ if (!Opts.ShowLineMarkers)
+ Res.push_back("-P");
+ if (Opts.ShowComments)
+ Res.push_back("-C");
+ if (Opts.ShowMacroComments)
+ Res.push_back("-CC");
+}
+
+static void TargetOptsToArgs(const TargetOptions &Opts,
+ std::vector<std::string> &Res) {
+ Res.push_back("-triple");
+ Res.push_back(Opts.Triple);
+ if (!Opts.CPU.empty()) {
+ Res.push_back("-target-cpu");
+ Res.push_back(Opts.CPU);
+ }
+ if (!Opts.ABI.empty()) {
+ Res.push_back("-target-abi");
+ Res.push_back(Opts.ABI);
+ }
+ for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) {
+ Res.push_back("-target-feature");
+ Res.push_back(Opts.Features[i]);
+ }
+}
+
+void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
+ AnalyzerOptsToArgs(getAnalyzerOpts(), Res);
+ CodeGenOptsToArgs(getCodeGenOpts(), Res);
+ DependencyOutputOptsToArgs(getDependencyOutputOpts(), Res);
+ DiagnosticOptsToArgs(getDiagnosticOpts(), Res);
+ FrontendOptsToArgs(getFrontendOpts(), Res);
+ HeaderSearchOptsToArgs(getHeaderSearchOpts(), Res);
+ LangOptsToArgs(getLangOpts(), Res);
+ PreprocessorOptsToArgs(getPreprocessorOpts(), Res);
+ PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), Res);
+ TargetOptsToArgs(getTargetOpts(), Res);
+}
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index 81d1179f28e3..c7f93595e1ea 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -12,12 +12,14 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/Utils.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/PPCallbacks.h"
-#include "clang/Lex/DirectoryLookup.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
@@ -42,11 +44,10 @@ private:
public:
DependencyFileCallback(const Preprocessor *_PP,
llvm::raw_ostream *_OS,
- const std::vector<std::string> &_Targets,
- bool _IncludeSystemHeaders,
- bool _PhonyTarget)
- : PP(_PP), Targets(_Targets), OS(_OS),
- IncludeSystemHeaders(_IncludeSystemHeaders), PhonyTarget(_PhonyTarget) {}
+ const DependencyOutputOptions &Opts)
+ : PP(_PP), Targets(Opts.Targets), OS(_OS),
+ IncludeSystemHeaders(Opts.IncludeSystemHeaders),
+ PhonyTarget(Opts.UsePhonyTargets) {}
~DependencyFileCallback() {
OutputDependencyFile();
@@ -59,18 +60,23 @@ public:
};
}
+void clang::AttachDependencyFileGen(Preprocessor &PP,
+ const DependencyOutputOptions &Opts) {
+ if (Opts.Targets.empty()) {
+ PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
+ return;
+ }
+ std::string Err;
+ llvm::raw_ostream *OS(new llvm::raw_fd_ostream(Opts.OutputFile.c_str(), Err));
+ if (!Err.empty()) {
+ PP.getDiagnostics().Report(diag::err_fe_error_opening)
+ << Opts.OutputFile << Err;
+ return;
+ }
-void clang::AttachDependencyFileGen(Preprocessor *PP, llvm::raw_ostream *OS,
- std::vector<std::string> &Targets,
- bool IncludeSystemHeaders,
- bool PhonyTarget) {
- assert(!Targets.empty() && "Target required for dependency generation");
-
- DependencyFileCallback *PPDep =
- new DependencyFileCallback(PP, OS, Targets, IncludeSystemHeaders,
- PhonyTarget);
- PP->setPPCallbacks(PPDep);
+ assert(!PP.getPPCallbacks() && "Preprocessor callbacks already registered!");
+ PP.setPPCallbacks(new DependencyFileCallback(&PP, OS, Opts));
}
/// FileMatchesDepCriteria - Determine whether the given Filename should be
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index d92d4cb7b8de..0263c30bfd57 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -135,7 +135,7 @@ void DocumentXML::finalize() {
for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
i != e; ++i) {
- if (i->first.hasQualifiers()) {
+ if (i->first.hasLocalQualifiers()) {
writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
@@ -205,7 +205,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
{
addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
- if (!pType.hasQualifiers())
+ if (!pType.hasLocalQualifiers())
{
Types[pType] = BasicTypes[pType.getTypePtr()];
}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
new file mode 100644
index 000000000000..ff63a0dab5f9
--- /dev/null
+++ b/lib/Frontend/FrontendAction.cpp
@@ -0,0 +1,225 @@
+//===--- FrontendAction.cpp -----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Sema/ParseAST.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+FrontendAction::FrontendAction() : Instance(0), CurrentTimer(0) {}
+
+FrontendAction::~FrontendAction() {}
+
+void FrontendAction::setCurrentFile(llvm::StringRef Value, ASTUnit *AST) {
+ CurrentFile = Value;
+ CurrentASTUnit.reset(AST);
+}
+
+bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
+ llvm::StringRef Filename,
+ bool IsAST) {
+ assert(!Instance && "Already processing a source file!");
+ assert(!Filename.empty() && "Unexpected empty filename!");
+ setCurrentFile(Filename);
+ setCompilerInstance(&CI);
+
+ // AST files follow a very different path, since they share objects via the
+ // AST unit.
+ if (IsAST) {
+ assert(!usesPreprocessorOnly() &&
+ "Attempt to pass AST file to preprocessor only action!");
+ assert(hasASTSupport() && "This action does not have AST support!");
+
+ std::string Error;
+ ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, &Error);
+ if (!AST) {
+ CI.getDiagnostics().Report(diag::err_fe_invalid_ast_file) << Error;
+ goto failure;
+ }
+
+ setCurrentFile(Filename, AST);
+
+ // Set the shared objects, these are reset when we finish processing the
+ // file, otherwise the CompilerInstance will happily destroy them.
+ CI.setFileManager(&AST->getFileManager());
+ CI.setSourceManager(&AST->getSourceManager());
+ CI.setPreprocessor(&AST->getPreprocessor());
+ CI.setASTContext(&AST->getASTContext());
+
+ // Initialize the action.
+ if (!BeginSourceFileAction(CI, Filename))
+ goto failure;
+
+ /// Create the AST consumer.
+ CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+ if (!CI.hasASTConsumer())
+ goto failure;
+
+ return true;
+ }
+
+ // Inform the diagnostic client we are processing a source file.
+ CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
+ &CI.getPreprocessor());
+
+ // Initialize the action.
+ if (!BeginSourceFileAction(CI, Filename))
+ goto failure;
+
+ /// Create the AST context and consumer unless this is a preprocessor only
+ /// action.
+ if (!usesPreprocessorOnly()) {
+ CI.createASTContext();
+ CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+ if (!CI.hasASTConsumer())
+ goto failure;
+
+ /// Use PCH?
+ if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
+ assert(hasPCHSupport() && "This action does not have PCH support!");
+ CI.createPCHExternalASTSource(
+ CI.getPreprocessorOpts().ImplicitPCHInclude);
+ if (!CI.getASTContext().getExternalSource())
+ goto failure;
+ }
+ }
+
+ // Initialize builtin info as long as we aren't using an external AST
+ // source.
+ if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
+ PP.getLangOptions().NoBuiltin);
+ }
+
+ return true;
+
+ // If we failed, reset state since the client will not end up calling the
+ // matching EndSourceFile().
+ failure:
+ if (isCurrentFileAST()) {
+ CI.takeASTContext();
+ CI.takePreprocessor();
+ CI.takeSourceManager();
+ CI.takeFileManager();
+ }
+
+ CI.getDiagnosticClient().EndSourceFile();
+ setCurrentFile("");
+ setCompilerInstance(0);
+ return false;
+}
+
+void FrontendAction::Execute() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // Initialize the main file entry. This needs to be delayed until after PCH
+ // has loaded.
+ if (isCurrentFileAST()) {
+ // Set the main file ID to an empty file.
+ //
+ // FIXME: We probably shouldn't need this, but for now this is the
+ // simplest way to reuse the logic in ParseAST.
+ const char *EmptyStr = "";
+ llvm::MemoryBuffer *SB =
+ llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>");
+ CI.getSourceManager().createMainFileIDForMemBuffer(SB);
+ } else {
+ if (!CI.InitializeSourceManager(getCurrentFile()))
+ return;
+ }
+
+ llvm::TimeRegion Timer(CurrentTimer);
+ ExecuteAction();
+}
+
+void FrontendAction::EndSourceFile() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // Finalize the action.
+ EndSourceFileAction();
+
+ // Release the consumer and the AST, in that order since the consumer may
+ // perform actions in its destructor which require the context.
+ //
+ // FIXME: There is more per-file stuff we could just drop here?
+ if (CI.getFrontendOpts().DisableFree) {
+ CI.takeASTConsumer();
+ if (!isCurrentFileAST())
+ CI.takeASTContext();
+ } else {
+ CI.setASTConsumer(0);
+ if (!isCurrentFileAST())
+ CI.setASTContext(0);
+ }
+
+ if (CI.getFrontendOpts().ShowStats) {
+ llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
+ CI.getPreprocessor().PrintStats();
+ CI.getPreprocessor().getIdentifierTable().PrintStats();
+ CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
+ CI.getSourceManager().PrintStats();
+ llvm::errs() << "\n";
+ }
+
+ // Cleanup the output streams, and erase the output files if we encountered
+ // an error.
+ CI.ClearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().getNumErrors());
+
+ // Inform the diagnostic client we are done with this source file.
+ CI.getDiagnosticClient().EndSourceFile();
+
+ if (isCurrentFileAST()) {
+ CI.takeASTContext();
+ CI.takePreprocessor();
+ CI.takeSourceManager();
+ CI.takeFileManager();
+ }
+
+ setCompilerInstance(0);
+ setCurrentFile("");
+}
+
+//===----------------------------------------------------------------------===//
+// Utility Actions
+//===----------------------------------------------------------------------===//
+
+void ASTFrontendAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // FIXME: Move the truncation aspect of this into Sema, we delayed this till
+ // here so the source manager would be initialized.
+ if (hasCodeCompletionSupport() &&
+ !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
+ CI.createCodeCompletionConsumer();
+
+ // Use a code completion consumer?
+ CodeCompleteConsumer *CompletionConsumer = 0;
+ if (CI.hasCodeCompletionConsumer())
+ CompletionConsumer = &CI.getCodeCompletionConsumer();
+
+ ParseAST(CI.getPreprocessor(), &CI.getASTConsumer(), CI.getASTContext(),
+ CI.getFrontendOpts().ShowStats,
+ usesCompleteTranslationUnit(), CompletionConsumer);
+}
+
+ASTConsumer *
+PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ llvm::llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
+}
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
new file mode 100644
index 000000000000..7a7537bce40f
--- /dev/null
+++ b/lib/Frontend/FrontendActions.cpp
@@ -0,0 +1,281 @@
+//===--- FrontendActions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/AnalysisConsumer.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FixItRewriter.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateAnalysisConsumer(CI.getPreprocessor(),
+ CI.getFrontendOpts().OutputFile,
+ CI.getAnalyzerOpts());
+}
+
+ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTPrinter(CI.createDefaultOutputFile(false, InFile));
+}
+
+ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTPrinterXML(CI.createDefaultOutputFile(false, InFile,
+ "xml"));
+}
+
+ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTDumper();
+}
+
+ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTViewer();
+}
+
+ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateDeclContextPrinter();
+}
+
+ASTConsumer *DumpRecordAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateRecordLayoutDumper();
+}
+
+ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
+ if (CI.getFrontendOpts().RelocatablePCH &&
+ Sysroot.empty()) {
+ CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
+ return 0;
+ }
+
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
+ if (CI.getFrontendOpts().RelocatablePCH)
+ return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
+
+ return CreatePCHGenerator(CI.getPreprocessor(), OS);
+}
+
+ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateHTMLPrinter(CI.createDefaultOutputFile(false, InFile),
+ CI.getPreprocessor());
+}
+
+ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
+}
+
+FixItAction::FixItAction() {}
+FixItAction::~FixItAction() {}
+
+ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new ASTConsumer();
+}
+
+/// AddFixItLocations - Add any individual user specified "fix-it" locations,
+/// and return true on success.
+static bool AddFixItLocations(CompilerInstance &CI,
+ FixItRewriter &FixItRewrite) {
+ const std::vector<ParsedSourceLocation> &Locs =
+ CI.getFrontendOpts().FixItLocations;
+ for (unsigned i = 0, e = Locs.size(); i != e; ++i) {
+ const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName);
+ if (!File) {
+ CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file)
+ << Locs[i].FileName;
+ return false;
+ }
+
+ RequestedSourceLocation Requested;
+ Requested.File = File;
+ Requested.Line = Locs[i].Line;
+ Requested.Column = Locs[i].Column;
+ FixItRewrite.addFixItLocation(Requested);
+ }
+
+ return true;
+}
+
+bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename) {
+ Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
+ CI.getLangOpts()));
+ if (!AddFixItLocations(CI, *Rewriter))
+ return false;
+
+ return true;
+}
+
+void FixItAction::EndSourceFileAction() {
+ const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
+ Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile);
+}
+
+ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateObjCRewriter(InFile,
+ CI.createDefaultOutputFile(true, InFile, "cpp"),
+ CI.getDiagnostics(), CI.getLangOpts(),
+ CI.getDiagnosticOpts().NoRewriteMacros);
+}
+
+ASTConsumer *RewriteBlocksAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateBlockRewriter(InFile, CI.getDiagnostics(), CI.getLangOpts());
+}
+
+ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new ASTConsumer();
+}
+
+CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {}
+
+ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ BackendAction BA = static_cast<BackendAction>(Act);
+ llvm::OwningPtr<llvm::raw_ostream> OS;
+ if (BA == Backend_EmitAssembly)
+ OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
+ else if (BA == Backend_EmitLL)
+ OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
+ else if (BA == Backend_EmitBC)
+ OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
+
+ return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(),
+ CI.getCodeGenOpts(), CI.getTargetOpts(), InFile,
+ OS.take(), CI.getLLVMContext());
+}
+
+EmitAssemblyAction::EmitAssemblyAction()
+ : CodeGenAction(Backend_EmitAssembly) {}
+
+EmitBCAction::EmitBCAction() : CodeGenAction(Backend_EmitBC) {}
+
+EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {}
+
+EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+void DumpRawTokensAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ SourceManager &SM = PP.getSourceManager();
+
+ // Start lexing the specified input file.
+ Lexer RawLex(SM.getMainFileID(), SM, PP.getLangOptions());
+ RawLex.SetKeepWhitespaceMode(true);
+
+ Token RawTok;
+ RawLex.LexFromRawLexer(RawTok);
+ while (RawTok.isNot(tok::eof)) {
+ PP.DumpToken(RawTok, true);
+ fprintf(stderr, "\n");
+ RawLex.LexFromRawLexer(RawTok);
+ }
+}
+
+void DumpTokensAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ // Start preprocessing the specified input file.
+ Token Tok;
+ PP.EnterMainSourceFile();
+ do {
+ PP.Lex(Tok);
+ PP.DumpToken(Tok, true);
+ fprintf(stderr, "\n");
+ } while (Tok.isNot(tok::eof));
+}
+
+void GeneratePTHAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ if (CI.getFrontendOpts().OutputFile.empty() ||
+ CI.getFrontendOpts().OutputFile == "-") {
+ // FIXME: Don't fail this way.
+ // FIXME: Verify that we can actually seek in the given file.
+ llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
+ ::exit(1);
+ }
+ llvm::raw_fd_ostream *OS =
+ CI.createDefaultOutputFile(true, getCurrentFile());
+ CacheTokens(CI.getPreprocessor(), OS);
+}
+
+void ParseOnlyAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ llvm::OwningPtr<Action> PA(new MinimalAction(PP));
+
+ Parser P(PP, *PA);
+ PP.EnterMainSourceFile();
+ P.ParseTranslationUnit();
+}
+
+void PreprocessOnlyAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+
+ Token Tok;
+ // Start parsing the specified input file.
+ PP.EnterMainSourceFile();
+ do {
+ PP.Lex(Tok);
+ } while (Tok.isNot(tok::eof));
+}
+
+void PrintParseAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
+
+ Parser P(PP, *PA);
+ PP.EnterMainSourceFile();
+ P.ParseTranslationUnit();
+}
+
+void PrintPreprocessedAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
+ CI.getPreprocessorOutputOpts());
+}
+
+void RewriteMacrosAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+ RewriteMacrosInInput(CI.getPreprocessor(), OS);
+}
+
+void RewriteTestAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ DoRewriteTest(CI.getPreprocessor(), OS);
+}
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
new file mode 100644
index 000000000000..bd916386056b
--- /dev/null
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -0,0 +1,31 @@
+//===--- FrontendOptions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+FrontendOptions::InputKind
+FrontendOptions::getInputKindForExtension(llvm::StringRef Extension) {
+ return llvm::StringSwitch<InputKind>(Extension)
+ .Case("ast", IK_AST)
+ .Case("c", IK_C)
+ .Cases("S", "s", IK_Asm)
+ .Case("i", IK_PreprocessedC)
+ .Case("ii", IK_PreprocessedCXX)
+ .Case("m", IK_ObjC)
+ .Case("mi", IK_PreprocessedObjC)
+ .Cases("mm", "M", IK_ObjCXX)
+ .Case("mii", IK_PreprocessedObjCXX)
+ .Case("C", IK_CXX)
+ .Cases("C", "cc", "cp", IK_CXX)
+ .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX)
+ .Case("cl", IK_OpenCL)
+ .Default(IK_C);
+}
diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp
index 145d53f3fc6e..3ba7abf38168 100644
--- a/lib/Frontend/HTMLDiagnostics.cpp
+++ b/lib/Frontend/HTMLDiagnostics.cpp
@@ -109,6 +109,8 @@ HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
ReportDiag(*D, FilesMade);
delete D;
}
+
+ BatchedDiags.clear();
}
void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index c0b4ebaab03b..d19ae9861ed6 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -11,12 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/InitHeaderSearch.h"
-#include "clang/Lex/HeaderSearch.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Lex/HeaderSearch.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/Config/config.h"
@@ -26,6 +30,66 @@
#include <windows.h>
#endif
using namespace clang;
+using namespace clang::frontend;
+
+namespace {
+
+/// InitHeaderSearch - This class makes it easier to set the search paths of
+/// a HeaderSearch object. InitHeaderSearch stores several search path lists
+/// internally, which can be sent to a HeaderSearch object in one swoop.
+class InitHeaderSearch {
+ std::vector<DirectoryLookup> IncludeGroup[4];
+ HeaderSearch& Headers;
+ bool Verbose;
+ std::string isysroot;
+
+public:
+
+ InitHeaderSearch(HeaderSearch &HS,
+ bool verbose = false, const std::string &iSysroot = "")
+ : Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
+
+ /// AddPath - Add the specified path to the specified group list.
+ void AddPath(const llvm::StringRef &Path, IncludeDirGroup Group,
+ bool isCXXAware, bool isUserSupplied,
+ bool isFramework, bool IgnoreSysRoot = false);
+
+ /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to suport a gnu
+ /// libstdc++.
+ void AddGnuCPlusPlusIncludePaths(const std::string &Base,
+ const char *ArchDir,
+ const char *Dir32,
+ const char *Dir64,
+ const llvm::Triple &triple);
+
+ /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW
+ /// libstdc++.
+ void AddMinGWCPlusPlusIncludePaths(const std::string &Base,
+ const char *Arch,
+ const char *Version);
+
+ /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
+ /// separator. The processing follows that of the CPATH variable for gcc.
+ void AddDelimitedPaths(const char *String);
+
+ // AddDefaultCIncludePaths - Add paths that should always be searched.
+ void AddDefaultCIncludePaths(const llvm::Triple &triple);
+
+ // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when
+ // compiling c++.
+ void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
+
+ /// AddDefaultSystemIncludePaths - Adds the default system include paths so
+ /// that e.g. stdio.h is found.
+ void AddDefaultSystemIncludePaths(const LangOptions &Lang,
+ const llvm::Triple &triple);
+
+ /// Realize - Merges all search path lists into one list and send it to
+ /// HeaderSearch.
+ void Realize();
+};
+
+}
void InitHeaderSearch::AddPath(const llvm::StringRef &Path,
IncludeDirGroup Group, bool isCXXAware,
@@ -82,9 +146,8 @@ void InitHeaderSearch::AddPath(const llvm::StringRef &Path,
}
-void InitHeaderSearch::AddEnvVarPaths(const char *Name) {
- const char* at = getenv(Name);
- if (!at || *at == 0) // Empty string should not add '.' path.
+void InitHeaderSearch::AddDelimitedPaths(const char *at) {
+ if (*at == 0) // Empty string should not add '.' path.
return;
const char* delim = strchr(at, llvm::sys::PathSeparator);
@@ -103,27 +166,30 @@ void InitHeaderSearch::AddEnvVarPaths(const char *Name) {
}
void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base,
+ const char *ArchDir,
const char *Dir32,
const char *Dir64,
const llvm::Triple &triple) {
+ // Add the common dirs
+ AddPath(Base, System, true, false, false);
+ AddPath(Base + "/backward", System, true, false, false);
+
+ // Add the multilib dirs
llvm::Triple::ArchType arch = triple.getArch();
bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
-
- AddPath(Base, System, true, false, false);
if (is64bit)
- AddPath(Base + "/" + Dir64, System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
else
- AddPath(Base + "/" + Dir32, System, true, false, false);
- AddPath(Base + "/backward", System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
}
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base,
const char *Arch,
const char *Version) {
- std::string 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);
+ std::string 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);
}
// FIXME: This probably should goto to some platform utils place.
@@ -243,6 +309,16 @@ bool getVisualStudioDir(std::string &path) {
void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
// FIXME: temporary hack: hard-coded paths.
+ llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ llvm::SmallVector<llvm::StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
+ i != dirs.end();
+ ++i)
+ AddPath(*i, System, false, false, false);
+ return;
+ }
llvm::Triple::OSType os = triple.getOS();
switch (os) {
case llvm::Triple::Win32:
@@ -288,6 +364,17 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
llvm::Triple::OSType os = triple.getOS();
+ llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
+ if (CxxIncludeRoot != "") {
+ llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
+ if (CxxIncludeArch == "")
+ AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
+ CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
+ else
+ AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
+ CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
+ return;
+ }
// FIXME: temporary hack: hard-coded paths.
switch (os) {
case llvm::Triple::Cygwin:
@@ -310,113 +397,77 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
break;
case llvm::Triple::Darwin:
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "i686-apple-darwin10",
- "i686-apple-darwin10/x86_64",
- triple);
+ "i686-apple-darwin10", "", "x86_64", triple);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
- "i686-apple-darwin8",
- "i686-apple-darwin8",
- triple);
+ "i686-apple-darwin8", "", "", triple);
break;
case llvm::Triple::Linux:
// Ubuntu 7.10 - Gutsy Gibbon
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
+ "i486-linux-gnu", "", "", triple);
// Ubuntu 9.04
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
- "x86_64-linux-gnu/32",
- "x86_64-linux-gnu",
- triple);
+ "x86_64-linux-gnu","32", "", triple);
+ // Ubuntu 9.10
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+ "x86_64-linux-gnu", "32", "", triple);
// Fedora 8
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
+ "i386-redhat-linux", "", "", triple);
// Fedora 9
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
+ "i386-redhat-linux", "", "", triple);
// Fedora 10
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
+ "i386-redhat-linux","", "", triple);
+
+ // Fedora 11
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+ "i586-redhat-linux","", "", triple);
+
// openSUSE 11.1 32 bit
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
+ "i586-suse-linux", "", "", triple);
// openSUSE 11.1 64 bit
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "x86_64-suse-linux/32",
- "x86_64-suse-linux",
- triple);
+ "x86_64-suse-linux", "32", "", triple);
// openSUSE 11.2
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
+ "i586-suse-linux", "", "", triple);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "x86_64-suse-linux",
- "x86_64-suse-linux",
- triple);
+ "x86_64-suse-linux", "", "", triple);
// Arch Linux 2008-06-24
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "i686-pc-linux-gnu", "", "", triple);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "x86_64-unknown-linux-gnu",
- "x86_64-unknown-linux-gnu",
- triple);
+ "x86_64-unknown-linux-gnu", "", "", triple);
// Gentoo x86 2009.1 stable
AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
// Gentoo x86 2009.0 stable
AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
// Gentoo x86 2008.0 stable
AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
// Ubuntu 8.10
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-pc-linux-gnu",
- "i486-pc-linux-gnu",
- triple);
+ "i486-pc-linux-gnu", "", "", triple);
// Ubuntu 9.04
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
+ "i486-linux-gnu","", "", triple);
// Gentoo amd64 stable
AddGnuCPlusPlusIncludePaths(
"/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "i686-pc-linux-gnu", "", "", triple);
// Exherbo (2009-10-26)
- AddGnuCPlusPlusIncludePaths(
- "/usr/include/c++/4.4.2",
- "x86_64-pc-linux-gnu/32",
- "x86_64-pc-linux-gnu",
- triple);
- AddGnuCPlusPlusIncludePaths(
- "/usr/include/c++/4.4.2",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+ "x86_64-pc-linux-gnu", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+ "i686-pc-linux-gnu", "", "", triple);
break;
case llvm::Triple::FreeBSD:
// DragonFly
@@ -429,44 +480,27 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
case llvm::Triple::AuroraUX:
// AuroraUX
AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
- "i386-pc-solaris2.11",
- "i386-pc-solaris2.11",
- triple);
+ "i386-pc-solaris2.11", "", "", triple);
break;
default:
break;
}
}
-void InitHeaderSearch::AddDefaultFrameworkIncludePaths(const llvm::Triple &triple) {
- llvm::Triple::OSType os = triple.getOS();
- if (os != llvm::Triple::Darwin)
- return;
- AddPath("/System/Library/Frameworks", System, true, false, true);
- AddPath("/Library/Frameworks", System, true, false, true);
-}
-
void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
const llvm::Triple &triple) {
AddDefaultCIncludePaths(triple);
- AddDefaultFrameworkIncludePaths(triple);
+
+ // Add the default framework include paths on Darwin.
+ if (triple.getOS() == llvm::Triple::Darwin) {
+ AddPath("/System/Library/Frameworks", System, true, false, true);
+ AddPath("/Library/Frameworks", System, true, false, true);
+ }
+
if (Lang.CPlusPlus)
AddDefaultCPlusPlusIncludePaths(triple);
}
-void InitHeaderSearch::AddDefaultEnvVarPaths(const LangOptions &Lang) {
- AddEnvVarPaths("CPATH");
- if (Lang.CPlusPlus && Lang.ObjC1)
- AddEnvVarPaths("OBJCPLUS_INCLUDE_PATH");
- else if (Lang.CPlusPlus)
- AddEnvVarPaths("CPLUS_INCLUDE_PATH");
- else if (Lang.ObjC1)
- AddEnvVarPaths("OBJC_INCLUDE_PATH");
- else
- AddEnvVarPaths("C_INCLUDE_PATH");
-}
-
-
/// RemoveDuplicates - If there are duplicate directory entries in the specified
/// search list, remove the later (dead) ones.
static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
@@ -591,3 +625,40 @@ void InitHeaderSearch::Realize() {
fprintf(stderr, "End of search list.\n");
}
}
+
+void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
+ const HeaderSearchOptions &HSOpts,
+ const LangOptions &Lang,
+ const llvm::Triple &Triple) {
+ InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
+
+ // Add the user defined entries.
+ for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
+ const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
+ Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
+ false);
+ }
+
+ // Add entries from CPATH and friends.
+ Init.AddDelimitedPaths(HSOpts.EnvIncPath.c_str());
+ if (Lang.CPlusPlus && Lang.ObjC1)
+ Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath.c_str());
+ else if (Lang.CPlusPlus)
+ Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath.c_str());
+ else if (Lang.ObjC1)
+ Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath.c_str());
+ else
+ Init.AddDelimitedPaths(HSOpts.CEnvIncPath.c_str());
+
+ if (!HSOpts.BuiltinIncludePath.empty()) {
+ // Ignore the sys root, we *always* look for clang headers relative to
+ // supplied path.
+ Init.AddPath(HSOpts.BuiltinIncludePath, System,
+ false, false, false, /*IgnoreSysRoot=*/ true);
+ }
+
+ if (HSOpts.UseStandardIncludes)
+ Init.AddDefaultSystemIncludePaths(Lang, Triple);
+
+ Init.Realize();
+}
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 7139e55f0b60..4ee286dd265d 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -11,8 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/InitPreprocessor.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/PreprocessorOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
@@ -60,9 +61,7 @@ static void UndefineBuiltinMacro(std::vector<char> &Buf, const char *Macro) {
Buf.push_back('\n');
}
-/// Add the quoted name of an implicit include file.
-static void AddQuotedIncludePath(std::vector<char> &Buf,
- const std::string &File) {
+std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
// Implicit include paths should be resolved relative to the current
// working directory first, and then use the regular header search
// mechanism. The proper way to handle this is to have the
@@ -75,9 +74,16 @@ static void AddQuotedIncludePath(std::vector<char> &Buf,
if (!Path.exists())
Path = File;
+ return Lexer::Stringify(Path.str());
+}
+
+/// Add the quoted name of an implicit include file.
+static void AddQuotedIncludePath(std::vector<char> &Buf,
+ const std::string &File) {
+
// Escape double quotes etc.
Buf.push_back('"');
- std::string EscapedFile = Lexer::Stringify(Path.str());
+ std::string EscapedFile = NormalizeDashIncludePath(File);
Buf.insert(Buf.end(), EscapedFile.begin(), EscapedFile.end());
Buf.push_back('"');
}
@@ -216,6 +222,14 @@ static void DefineTypeSize(const char *MacroName, unsigned TypeWidth,
DefineBuiltinMacro(Buf, MacroBuf);
}
+/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
+/// the width, suffix, and signedness of the given type
+static void DefineTypeSize(const char *MacroName, TargetInfo::IntType Ty,
+ const TargetInfo &TI, std::vector<char> &Buf) {
+ DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
+ TI.isTypeSigned(Ty), Buf);
+}
+
static void DefineType(const char *MacroName, TargetInfo::IntType Ty,
std::vector<char> &Buf) {
char MacroBuf[60];
@@ -223,6 +237,20 @@ static void DefineType(const char *MacroName, TargetInfo::IntType Ty,
DefineBuiltinMacro(Buf, MacroBuf);
}
+static void DefineExactWidthIntType(TargetInfo::IntType Ty,
+ const TargetInfo &TI, std::vector<char> &Buf) {
+ char MacroBuf[60];
+ int TypeWidth = TI.getTypeWidth(Ty);
+ sprintf(MacroBuf, "__INT%d_TYPE__", TypeWidth);
+ DefineType(MacroBuf, Ty, Buf);
+
+
+ const char *ConstSuffix = TargetInfo::getTypeConstantSuffix(Ty);
+ if (strlen(ConstSuffix) > 0) {
+ sprintf(MacroBuf, "__INT%d_C_SUFFIX__=%s", TypeWidth, ConstSuffix);
+ DefineBuiltinMacro(Buf, MacroBuf);
+ }
+}
static void InitializePredefinedMacros(const TargetInfo &TI,
const LangOptions &LangOpts,
@@ -346,14 +374,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineBuiltinMacro(Buf, "__CHAR_BIT__=8");
DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Buf);
- DefineTypeSize("__SHRT_MAX__", TI.getShortWidth(), "", true, Buf);
- DefineTypeSize("__INT_MAX__", TI.getIntWidth(), "", true, Buf);
- DefineTypeSize("__LONG_MAX__", TI.getLongWidth(), "L", true, Buf);
- DefineTypeSize("__LONG_LONG_MAX__", TI.getLongLongWidth(), "LL", true, Buf);
- DefineTypeSize("__WCHAR_MAX__", TI.getWCharWidth(), "", true, Buf);
- TargetInfo::IntType IntMaxType = TI.getIntMaxType();
- DefineTypeSize("__INTMAX_MAX__", TI.getTypeWidth(IntMaxType),
- TI.getTypeConstantSuffix(IntMaxType), true, Buf);
+ DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Buf);
+ DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Buf);
+ DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Buf);
+ DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Buf);
+ DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Buf);
+ DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Buf);
DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Buf);
DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Buf);
@@ -374,23 +400,22 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (!LangOpts.CharIsSigned)
DefineBuiltinMacro(Buf, "__CHAR_UNSIGNED__");
- // Define fixed-sized integer types for stdint.h
- assert(TI.getCharWidth() == 8 && "unsupported target types");
- assert(TI.getShortWidth() == 16 && "unsupported target types");
- DefineBuiltinMacro(Buf, "__INT8_TYPE__=char");
- DefineBuiltinMacro(Buf, "__INT16_TYPE__=short");
-
- if (TI.getIntWidth() == 32)
- DefineBuiltinMacro(Buf, "__INT32_TYPE__=int");
- else {
- assert(TI.getLongLongWidth() == 32 && "unsupported target types");
- DefineBuiltinMacro(Buf, "__INT32_TYPE__=long long");
- }
-
- // 16-bit targets doesn't necessarily have a 64-bit type.
- if (TI.getLongLongWidth() == 64)
- DefineType("__INT64_TYPE__", TI.getInt64Type(), Buf);
+ // Define exact-width integer types for stdint.h
+ sprintf(MacroBuf, "__INT%d_TYPE__=char", TI.getCharWidth());
+ DefineBuiltinMacro(Buf, MacroBuf);
+ if (TI.getShortWidth() > TI.getCharWidth())
+ DefineExactWidthIntType(TargetInfo::SignedShort, TI, Buf);
+
+ if (TI.getIntWidth() > TI.getShortWidth())
+ DefineExactWidthIntType(TargetInfo::SignedInt, TI, Buf);
+
+ if (TI.getLongWidth() > TI.getIntWidth())
+ DefineExactWidthIntType(TargetInfo::SignedLong, TI, Buf);
+
+ if (TI.getLongLongWidth() > TI.getLongWidth())
+ DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Buf);
+
// Add __builtin_va_list typedef.
{
const char *VAList = TI.getVAListDeclaration();
@@ -443,7 +468,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
/// environment ready to process a single file. This returns true on error.
///
void clang::InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions &InitOpts) {
+ const PreprocessorOptions &InitOpts,
+ const HeaderSearchOptions &HSOpts) {
std::vector<char> PredefineBuffer;
const char *LineDirective = "# 1 \"<built-in>\" 3\n";
@@ -451,7 +477,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
- if (InitOpts.getUsePredefines())
+ if (InitOpts.UsePredefines)
InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
PredefineBuffer);
@@ -462,30 +488,33 @@ void clang::InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Process #define's and #undef's in the order they are given.
- for (PreprocessorInitOptions::macro_iterator I = InitOpts.macro_begin(),
- E = InitOpts.macro_end(); I != E; ++I) {
- if (I->second) // isUndef
- UndefineBuiltinMacro(PredefineBuffer, I->first.c_str());
+ for (unsigned i = 0, e = InitOpts.Macros.size(); i != e; ++i) {
+ if (InitOpts.Macros[i].second) // isUndef
+ UndefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str());
else
- DefineBuiltinMacro(PredefineBuffer, I->first.c_str());
+ DefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str());
}
// If -imacros are specified, include them now. These are processed before
// any -include directives.
- for (PreprocessorInitOptions::imacro_iterator I = InitOpts.imacro_begin(),
- E = InitOpts.imacro_end(); I != E; ++I)
- AddImplicitIncludeMacros(PredefineBuffer, *I);
+ for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
+ AddImplicitIncludeMacros(PredefineBuffer, InitOpts.MacroIncludes[i]);
// Process -include directives.
- for (PreprocessorInitOptions::include_iterator I = InitOpts.include_begin(),
- E = InitOpts.include_end(); I != E; ++I) {
- if (I->second) // isPTH
- AddImplicitIncludePTH(PredefineBuffer, PP, I->first);
+ for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
+ const std::string &Path = InitOpts.Includes[i];
+ if (Path == InitOpts.ImplicitPTHInclude)
+ AddImplicitIncludePTH(PredefineBuffer, PP, Path);
else
- AddImplicitInclude(PredefineBuffer, I->first);
+ AddImplicitInclude(PredefineBuffer, Path);
}
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
PP.setPredefines(&PredefineBuffer[0]);
+
+ // Initialize the header search object.
+ ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), HSOpts,
+ PP.getLangOptions(),
+ PP.getTargetInfo().getTriple());
}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 26f426ba329b..ca7aa3260c62 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -13,6 +13,7 @@
#include "clang/Frontend/PCHReader.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -104,6 +105,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+ PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
Reader.Diag(diag::warn_pch_gc_mode)
<< LangOpts.getGCMode() << PPLangOpts.getGCMode();
@@ -121,83 +123,56 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
return false;
}
-bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
- if (Triple != PP.getTargetInfo().getTriple().getTriple()) {
- Reader.Diag(diag::warn_pch_target_triple)
- << Triple << PP.getTargetInfo().getTriple().getTriple();
- return true;
- }
- return false;
-}
-
-/// \brief Split the given string into a vector of lines, eliminating
-/// any empty lines in the process.
-///
-/// \param Str the string to split.
-/// \param Len the length of Str.
-/// \param KeepEmptyLines true if empty lines should be included
-/// \returns a vector of lines, with the line endings removed
-static std::vector<std::string> splitLines(const char *Str, unsigned Len,
- bool KeepEmptyLines = false) {
- std::vector<std::string> Lines;
- for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
- unsigned LineEnd = LineStart;
- while (LineEnd < Len && Str[LineEnd] != '\n')
- ++LineEnd;
- if (LineStart != LineEnd || KeepEmptyLines)
- Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
- LineStart = LineEnd;
- }
- return Lines;
-}
-
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static bool startsWith(const std::string &Haystack, const char *Needle) {
- for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
- if (I == N)
- return false;
- if (Haystack[I] != Needle[I])
- return false;
- }
+bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
+ if (Triple == PP.getTargetInfo().getTriple().str())
+ return false;
+ Reader.Diag(diag::warn_pch_target_triple)
+ << Triple << PP.getTargetInfo().getTriple().str();
return true;
}
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static inline bool startsWith(const std::string &Haystack,
- const std::string &Needle) {
- return startsWith(Haystack, Needle.c_str());
-}
-
-bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID,
+ llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
- const char *Predef = PP.getPredefines().c_str();
- unsigned PredefLen = PP.getPredefines().size();
-
- // If the two predefines buffers compare equal, we're done!
- if (PredefLen == PCHPredefLen &&
- strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
+ // We are in the context of an implicit include, so the predefines buffer will
+ // have a #include entry for the PCH file itself (as normalized by the
+ // preprocessor initialization). Find it and skip over it in the checking
+ // below.
+ llvm::SmallString<256> PCHInclude;
+ PCHInclude += "#include \"";
+ PCHInclude += NormalizeDashIncludePath(OriginalFileName);
+ PCHInclude += "\"\n";
+ std::pair<llvm::StringRef,llvm::StringRef> Split =
+ llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
+ llvm::StringRef Left = Split.first, Right = Split.second;
+ assert(Left != PP.getPredefines() && "Missing PCH include entry!");
+
+ // If the predefines is equal to the joined left and right halves, we're done!
+ if (Left.size() + Right.size() == PCHPredef.size() &&
+ PCHPredef.startswith(Left) && PCHPredef.endswith(Right))
return false;
SourceManager &SourceMgr = PP.getSourceManager();
- // The predefines buffers are different. Determine what the
- // differences are, and whether they require us to reject the PCH
- // file.
- std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
- std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
+ // The predefines buffers are different. Determine what the differences are,
+ // and whether they require us to reject the PCH file.
+ llvm::SmallVector<llvm::StringRef, 8> PCHLines;
+ PCHPredef.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+ llvm::SmallVector<llvm::StringRef, 8> CmdLineLines;
+ Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ Right.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
- // Sort both sets of predefined buffer lines, since
+ // Sort both sets of predefined buffer lines, since we allow some extra
+ // definitions and they may appear at any point in the output.
std::sort(CmdLineLines.begin(), CmdLineLines.end());
std::sort(PCHLines.begin(), PCHLines.end());
- // Determine which predefines that where used to build the PCH file
- // are missing from the command line.
- std::vector<std::string> MissingPredefines;
+ // Determine which predefines that were used to build the PCH file are missing
+ // from the command line.
+ std::vector<llvm::StringRef> MissingPredefines;
std::set_difference(PCHLines.begin(), PCHLines.end(),
CmdLineLines.begin(), CmdLineLines.end(),
std::back_inserter(MissingPredefines));
@@ -205,31 +180,30 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
bool MissingDefines = false;
bool ConflictingDefines = false;
for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
- const std::string &Missing = MissingPredefines[I];
- if (!startsWith(Missing, "#define ") != 0) {
+ llvm::StringRef Missing = MissingPredefines[I];
+ if (!Missing.startswith("#define ")) {
Reader.Diag(diag::warn_pch_compiler_options_mismatch);
return true;
}
- // This is a macro definition. Determine the name of the macro
- // we're defining.
+ // This is a macro definition. Determine the name of the macro we're
+ // defining.
std::string::size_type StartOfMacroName = strlen("#define ");
std::string::size_type EndOfMacroName
= Missing.find_first_of("( \n\r", StartOfMacroName);
assert(EndOfMacroName != std::string::npos &&
"Couldn't find the end of the macro name");
- std::string MacroName = Missing.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
+ llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
- // Determine whether this macro was given a different definition
- // on the command line.
- std::string MacroDefStart = "#define " + MacroName;
+ // Determine whether this macro was given a different definition on the
+ // command line.
+ std::string MacroDefStart = "#define " + MacroName.str();
std::string::size_type MacroDefLen = MacroDefStart.size();
- std::vector<std::string>::iterator ConflictPos
+ llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos
= std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
MacroDefStart);
for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
- if (!startsWith(*ConflictPos, MacroDefStart)) {
+ if (!ConflictPos->startswith(MacroDefStart)) {
// Different macro; we're done.
ConflictPos = CmdLineLines.end();
break;
@@ -250,21 +224,18 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
<< MacroName;
// Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
- Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
- << MacroName;
+ llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+ assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
ConflictingDefines = true;
continue;
}
- // If the macro doesn't conflict, then we'll just pick up the
- // macro definition from the PCH file. Warn the user that they
- // made a mistake.
+ // If the macro doesn't conflict, then we'll just pick up the macro
+ // definition from the PCH file. Warn the user that they made a mistake.
if (ConflictingDefines)
continue; // Don't complain if there are already conflicting defs
@@ -274,10 +245,9 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
}
// Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+ assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
.getFileLocWithOffset(Offset);
Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
}
@@ -289,13 +259,13 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
// parameters that were not present when building the PCH
// file. Extra #defines are okay, so long as the identifiers being
// defined were not used within the precompiled header.
- std::vector<std::string> ExtraPredefines;
+ std::vector<llvm::StringRef> ExtraPredefines;
std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
PCHLines.begin(), PCHLines.end(),
std::back_inserter(ExtraPredefines));
for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
- const std::string &Extra = ExtraPredefines[I];
- if (!startsWith(Extra, "#define ") != 0) {
+ llvm::StringRef &Extra = ExtraPredefines[I];
+ if (!Extra.startswith("#define ")) {
Reader.Diag(diag::warn_pch_compiler_options_mismatch);
return true;
}
@@ -307,16 +277,13 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
= Extra.find_first_of("( \n\r", StartOfMacroName);
assert(EndOfMacroName != std::string::npos &&
"Couldn't find the end of the macro name");
- std::string MacroName = Extra.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
+ llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
// Check whether this name was used somewhere in the PCH file. If
// so, defining it as a macro could change behavior, so we reject
// the PCH file.
- if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
- MacroName.c_str() + MacroName.size())) {
- Reader.Diag(diag::warn_macro_name_used_in_pch)
- << II;
+ if (IdentifierInfo *II = Reader.get(MacroName)) {
+ Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
return true;
}
@@ -650,11 +617,11 @@ bool PCHReader::Error(const char *Msg) {
///
/// \returns true if there was a mismatch (in which case the PCH file
/// should be ignored), or false otherwise.
-bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID) {
if (Listener)
- return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
+ return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID,
+ ActualOriginalFileName,
SuggestedPredefines);
return false;
}
@@ -1364,7 +1331,8 @@ PCHReader::ReadPCHBlock() {
break;
case pch::ORIGINAL_FILE_NAME:
- OriginalFileName.assign(BlobStart, BlobLen);
+ ActualOriginalFileName.assign(BlobStart, BlobLen);
+ OriginalFileName = ActualOriginalFileName;
MaybeAddSystemRootToFilename(OriginalFileName);
break;
@@ -1403,10 +1371,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
//
// FIXME: This shouldn't be here, we should just take a raw_ostream.
std::string ErrStr;
- if (FileName == "-")
- Buffer.reset(llvm::MemoryBuffer::getSTDIN());
- else
- Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
+ Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
if (!Buffer) {
Error(ErrStr.c_str());
return IgnorePCH;
@@ -1478,7 +1443,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
}
// Check the predefines buffer.
- if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
+ if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen),
PCHPredefinesBufferID))
return IgnorePCH;
@@ -1741,6 +1706,7 @@ bool PCHReader::ParseLanguageOptions(
PARSE_LANGOPT(NoInline);
PARSE_LANGOPT(AccessControl);
PARSE_LANGOPT(CharIsSigned);
+ PARSE_LANGOPT(ShortWChar);
LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
++Idx;
LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
@@ -2213,6 +2179,14 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
return ReadDeclExpr();
case TemplateArgument::Type:
return GetDeclaratorInfo(Record, Index);
+ case TemplateArgument::Template: {
+ SourceLocation
+ QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
+ QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
+ TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
+ return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
+ TemplateNameLoc);
+ }
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index b9ece21f74c3..6a92a2db51a8 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -264,7 +264,12 @@ void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
ClassRefs.reserve(NumClassRefs);
for (unsigned I = 0; I != NumClassRefs; ++I)
ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
- CD->setClassList(*Reader.getContext(), ClassRefs.data(), NumClassRefs);
+ llvm::SmallVector<SourceLocation, 16> SLocs;
+ SLocs.reserve(NumClassRefs);
+ for (unsigned I = 0; I != NumClassRefs; ++I)
+ SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(),
+ NumClassRefs);
}
void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
@@ -442,6 +447,8 @@ Attr *PCHReader::ReadAttributes() {
(BlocksAttr::BlocksAttrTypes)Record[Idx++]);
break;
+ SIMPLE_ATTR(CDecl);
+
case Attr::Cleanup:
New = ::new (*Context) CleanupAttr(
cast<FunctionDecl>(GetDecl(Record[Idx++])));
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index de56166125ed..8a45ebce1b9d 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -765,6 +765,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
// be enabled.
Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or
// unsigned type
+ Record.push_back(LangOpts.ShortWChar); // force wchar_t to be unsigned short
Record.push_back(LangOpts.getGCMode());
Record.push_back(LangOpts.getVisibilityMode());
Record.push_back(LangOpts.getStackProtectorMode());
@@ -1247,9 +1248,9 @@ void PCHWriter::WriteType(QualType T) {
// Emit the type's representation.
PCHTypeWriter W(*this, Record);
- if (T.hasNonFastQualifiers()) {
- Qualifiers Qs = T.getQualifiers();
- AddTypeRef(T.getUnqualifiedType(), Record);
+ if (T.hasLocalNonFastQualifiers()) {
+ Qualifiers Qs = T.getLocalQualifiers();
+ AddTypeRef(T.getLocalUnqualifiedType(), Record);
Record.push_back(Qs.getAsOpaqueValue());
W.Code = pch::TYPE_EXT_QUAL;
} else {
@@ -1767,6 +1768,9 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
break;
+ case Attr::CDecl:
+ break;
+
case Attr::Cleanup:
AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
break;
@@ -2118,6 +2122,12 @@ void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
case TemplateArgument::Type:
AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record);
break;
+ case TemplateArgument::Template:
+ Record.push_back(
+ Arg.getTemplateQualifierRange().getBegin().getRawEncoding());
+ Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding());
+ Record.push_back(Arg.getTemplateNameLoc().getRawEncoding());
+ break;
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
@@ -2144,10 +2154,10 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
return;
}
- unsigned FastQuals = T.getFastQualifiers();
+ unsigned FastQuals = T.getLocalFastQualifiers();
T.removeFastQualifiers();
- if (T.hasNonFastQualifiers()) {
+ if (T.hasLocalNonFastQualifiers()) {
pch::TypeID &ID = TypeIDs[T];
if (ID == 0) {
// We haven't seen these qualifiers applied to this type before.
@@ -2162,7 +2172,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
return;
}
- assert(!T.hasQualifiers());
+ assert(!T.hasLocalQualifiers());
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
pch::TypeID ID = 0;
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 8997e661a5a1..c7bfee2c8bcd 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -260,7 +260,9 @@ void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
VisitDecl(D);
Record.push_back(D->size());
for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
- Writer.AddDeclRef(*I, Record);
+ Writer.AddDeclRef(I->getInterface(), Record);
+ for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
+ Writer.AddSourceLocation(I->getLocation(), Record);
Code = pch::DECL_OBJC_CLASS;
}
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
index 1be9ea8b8c41..6bcf39a92a24 100644
--- a/lib/Frontend/PlistDiagnostics.cpp
+++ b/lib/Frontend/PlistDiagnostics.cpp
@@ -37,6 +37,7 @@ namespace {
const std::string OutputFile;
const LangOptions &LangOpts;
llvm::OwningPtr<PathDiagnosticClient> SubPD;
+ bool flushed;
public:
PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
PathDiagnosticClient *subPD);
@@ -61,7 +62,7 @@ namespace {
PlistDiagnostics::PlistDiagnostics(const std::string& output,
const LangOptions &LO,
PathDiagnosticClient *subPD)
- : OutputFile(output), LangOpts(LO), SubPD(subPD) {}
+ : OutputFile(output), LangOpts(LO), SubPD(subPD), flushed(false) {}
PathDiagnosticClient*
clang::CreatePlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
@@ -310,6 +311,11 @@ void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
*FilesMade) {
+
+ if (flushed)
+ return;
+
+ flushed = true;
// Build up a set of FIDs that we use by scanning the locations and
// ranges of the diagnostics.
@@ -423,4 +429,6 @@ void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
if (FilesMade)
FilesMade->push_back(OutputFile);
+
+ BatchedDiags.clear();
}
diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp
index 25b40c78183c..deb5498b906e 100644
--- a/lib/Frontend/PrintParserCallbacks.cpp
+++ b/lib/Frontend/PrintParserCallbacks.cpp
@@ -79,10 +79,11 @@ namespace {
/// Scope will always be top level file scope.
Action::DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
unsigned NumElts) {
Out << __FUNCTION__ << "\n";
return MinimalAction::ActOnForwardClassDeclaration(AtClassLoc, IdentList,
- NumElts);
+ IdentLocs, NumElts);
}
// Pure Printing
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 630a093a4bf6..37424057809c 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -13,13 +13,14 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/Utils.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Pragma.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/TokenConcatenation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
@@ -439,7 +440,7 @@ namespace {
};
}
-void clang::DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
+static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
// -dM mode just scans and ignores all tokens in the files, then dumps out
// the macro table at the end.
PP.EnterMainSourceFile();
@@ -467,18 +468,23 @@ void clang::DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
/// DoPrintPreprocessedInput - This implements -E mode.
///
void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
- bool EnableCommentOutput,
- bool EnableMacroCommentOutput,
- bool DisableLineMarkers,
- bool DumpDefines) {
+ const PreprocessorOutputOptions &Opts) {
+ // Show macros with no output is handled specially.
+ if (!Opts.ShowCPP) {
+ assert(Opts.ShowMacros && "Not yet implemented!");
+ DoPrintMacros(PP, OS);
+ return;
+ }
+
// Inform the preprocessor whether we want it to retain comments or not, due
// to -C or -CC.
- PP.SetCommentRetentionState(EnableCommentOutput, EnableMacroCommentOutput);
+ PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
OS->SetBufferSize(64*1024);
PrintPPOutputPPCallbacks *Callbacks =
- new PrintPPOutputPPCallbacks(PP, *OS, DisableLineMarkers, DumpDefines);
+ new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
+ Opts.ShowMacros);
PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
Callbacks));
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 24ad69e3e0d3..06955e5c30b6 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -744,7 +744,7 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
typedefString += "\n";
for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
I != E; ++I) {
- ObjCInterfaceDecl *ForwardDecl = *I;
+ ObjCInterfaceDecl *ForwardDecl = I->getInterface();
typedefString += "#ifndef _REWRITER_typedef_";
typedefString += ForwardDecl->getNameAsString();
typedefString += "\n";
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 4f8c804844b0..6ab0e1605276 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -39,9 +39,16 @@ static const enum llvm::raw_ostream::Colors savedColor =
const unsigned WordWrapIndentation = 6;
TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream &os,
- const DiagnosticOptions &diags)
+ const DiagnosticOptions &diags,
+ bool _OwnsOutputStream)
: OS(os), LangOpts(0), DiagOpts(&diags),
- LastCaretDiagnosticWasNote(false) {
+ LastCaretDiagnosticWasNote(0),
+ OwnsOutputStream(_OwnsOutputStream) {
+}
+
+TextDiagnosticPrinter::~TextDiagnosticPrinter() {
+ if (OwnsOutputStream)
+ delete &OS;
}
void TextDiagnosticPrinter::
diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp
new file mode 100644
index 000000000000..2891aec50444
--- /dev/null
+++ b/lib/Frontend/VerifyDiagnosticsClient.cpp
@@ -0,0 +1,344 @@
+//===--- VerifyDiagnosticsClient.cpp - Verifying Diagnostic Client --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+VerifyDiagnosticsClient::VerifyDiagnosticsClient(Diagnostic &_Diags,
+ DiagnosticClient *_Primary)
+ : Diags(_Diags), PrimaryClient(_Primary),
+ Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0), NumErrors(0) {
+}
+
+VerifyDiagnosticsClient::~VerifyDiagnosticsClient() {
+ CheckDiagnostics();
+}
+
+// DiagnosticClient interface.
+
+void VerifyDiagnosticsClient::BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP) {
+ // FIXME: Const hack, we screw up the preprocessor but in practice its ok
+ // because it doesn't get reused. It would be better if we could make a copy
+ // though.
+ CurrentPreprocessor = const_cast<Preprocessor*>(PP);
+
+ PrimaryClient->BeginSourceFile(LangOpts, PP);
+}
+
+void VerifyDiagnosticsClient::EndSourceFile() {
+ CheckDiagnostics();
+
+ PrimaryClient->EndSourceFile();
+
+ CurrentPreprocessor = 0;
+}
+
+void VerifyDiagnosticsClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ // Send the diagnostic to the buffer, we will check it once we reach the end
+ // of the source file (or are destructed).
+ Buffer->HandleDiagnostic(DiagLevel, Info);
+}
+
+// FIXME: It would be nice to just get this from the primary diagnostic client
+// or something.
+bool VerifyDiagnosticsClient::HadErrors() {
+ CheckDiagnostics();
+
+ return NumErrors != 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Checking diagnostics implementation.
+//===----------------------------------------------------------------------===//
+
+typedef TextDiagnosticBuffer::DiagList DiagList;
+typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+
+/// FindDiagnostics - Go through the comment and see if it indicates expected
+/// diagnostics. If so, then put them in a diagnostic list.
+///
+static void FindDiagnostics(const char *CommentStart, unsigned CommentLen,
+ DiagList &ExpectedDiags,
+ Preprocessor &PP, SourceLocation Pos,
+ const char *ExpectedStr) {
+ const char *CommentEnd = CommentStart+CommentLen;
+ unsigned ExpectedStrLen = strlen(ExpectedStr);
+
+ // Find all expected-foo diagnostics in the string and add them to
+ // ExpectedDiags.
+ while (CommentStart != CommentEnd) {
+ CommentStart = std::find(CommentStart, CommentEnd, 'e');
+ if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return;
+
+ // If this isn't expected-foo, ignore it.
+ if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) {
+ ++CommentStart;
+ continue;
+ }
+
+ CommentStart += ExpectedStrLen;
+
+ // Skip whitespace.
+ while (CommentStart != CommentEnd &&
+ isspace(CommentStart[0]))
+ ++CommentStart;
+
+ // Default, if we find the '{' now, is 1 time.
+ int Times = 1;
+ int Temp = 0;
+ // In extended syntax, there could be a digit now.
+ while (CommentStart != CommentEnd &&
+ CommentStart[0] >= '0' && CommentStart[0] <= '9') {
+ Temp *= 10;
+ Temp += CommentStart[0] - '0';
+ ++CommentStart;
+ }
+ if (Temp > 0)
+ Times = Temp;
+
+ // Skip whitespace again.
+ while (CommentStart != CommentEnd &&
+ isspace(CommentStart[0]))
+ ++CommentStart;
+
+ // We should have a {{ now.
+ if (CommentEnd-CommentStart < 2 ||
+ CommentStart[0] != '{' || CommentStart[1] != '{') {
+ if (std::find(CommentStart, CommentEnd, '{') != CommentEnd)
+ PP.Diag(Pos, diag::err_verify_bogus_characters);
+ else
+ PP.Diag(Pos, diag::err_verify_missing_start);
+ return;
+ }
+ CommentStart += 2;
+
+ // Find the }}.
+ const char *ExpectedEnd = CommentStart;
+ while (1) {
+ ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}');
+ if (CommentEnd-ExpectedEnd < 2) {
+ PP.Diag(Pos, diag::err_verify_missing_end);
+ return;
+ }
+
+ if (ExpectedEnd[1] == '}')
+ break;
+
+ ++ExpectedEnd; // Skip over singular }'s
+ }
+
+ std::string Msg(CommentStart, ExpectedEnd);
+ std::string::size_type FindPos;
+ while ((FindPos = Msg.find("\\n")) != std::string::npos)
+ Msg.replace(FindPos, 2, "\n");
+ // Add is possibly multiple times.
+ for (int i = 0; i < Times; ++i)
+ ExpectedDiags.push_back(std::make_pair(Pos, Msg));
+
+ CommentStart = ExpectedEnd;
+ }
+}
+
+/// FindExpectedDiags - Lex the main source file to find all of the
+// expected errors and warnings.
+static void FindExpectedDiags(Preprocessor &PP,
+ DiagList &ExpectedErrors,
+ DiagList &ExpectedWarnings,
+ DiagList &ExpectedNotes) {
+ // Create a raw lexer to pull all the comments out of the main file. We don't
+ // want to look in #include'd headers for expected-error strings.
+ FileID FID = PP.getSourceManager().getMainFileID();
+ if (PP.getSourceManager().getMainFileID().isInvalid())
+ return;
+
+ // Create a lexer to lex all the tokens of the main file in raw mode.
+ Lexer RawLex(FID, PP.getSourceManager(), PP.getLangOptions());
+
+ // Return comments as tokens, this is how we find expected diagnostics.
+ RawLex.SetCommentRetentionState(true);
+
+ Token Tok;
+ Tok.setKind(tok::comment);
+ while (Tok.isNot(tok::eof)) {
+ RawLex.Lex(Tok);
+ if (!Tok.is(tok::comment)) continue;
+
+ std::string Comment = PP.getSpelling(Tok);
+ if (Comment.empty()) continue;
+
+ // Find all expected errors.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP,
+ Tok.getLocation(), "expected-error");
+
+ // Find all expected warnings.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP,
+ Tok.getLocation(), "expected-warning");
+
+ // Find all expected notes.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP,
+ Tok.getLocation(), "expected-note");
+ };
+}
+
+/// PrintProblem - This takes a diagnostic map of the delta between expected and
+/// seen diagnostics. If there's anything in it, then something unexpected
+/// happened. Print the map out in a nice format and return "true". If the map
+/// is empty and we're not going to print things, then return "false".
+///
+static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
+ const_diag_iterator diag_begin,
+ const_diag_iterator diag_end,
+ const char *Kind, bool Expected) {
+ if (diag_begin == diag_end) return 0;
+
+ llvm::SmallString<256> Fmt;
+ llvm::raw_svector_ostream OS(Fmt);
+ for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
+ if (I->first.isInvalid() || !SourceMgr)
+ OS << "\n (frontend)";
+ else
+ OS << "\n Line " << SourceMgr->getInstantiationLineNumber(I->first);
+ OS << ": " << I->second;
+ }
+
+ Diags.Report(diag::err_verify_inconsistent_diags)
+ << Kind << !Expected << OS.str();
+ return std::distance(diag_begin, diag_end);
+}
+
+/// CompareDiagLists - Compare two diagnostic lists and return the difference
+/// between them.
+///
+static unsigned CompareDiagLists(Diagnostic &Diags,
+ SourceManager &SourceMgr,
+ const_diag_iterator d1_begin,
+ const_diag_iterator d1_end,
+ const_diag_iterator d2_begin,
+ const_diag_iterator d2_end,
+ const char *Label) {
+ DiagList LeftOnly;
+ DiagList Left(d1_begin, d1_end);
+ DiagList Right(d2_begin, d2_end);
+
+ for (const_diag_iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
+ unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(I->first);
+ const std::string &Diag1 = I->second;
+
+ DiagList::iterator II, IE;
+ for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
+ unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+ if (LineNo1 != LineNo2) continue;
+
+ const std::string &Diag2 = II->second;
+ if (Diag2.find(Diag1) != std::string::npos ||
+ Diag1.find(Diag2) != std::string::npos) {
+ break;
+ }
+ }
+ if (II == IE) {
+ // Not found.
+ LeftOnly.push_back(*I);
+ } else {
+ // Found. The same cannot be found twice.
+ Right.erase(II);
+ }
+ }
+ // Now all that's left in Right are those that were not matched.
+
+ return (PrintProblem(Diags, &SourceMgr,
+ LeftOnly.begin(), LeftOnly.end(), Label, true) +
+ PrintProblem(Diags, &SourceMgr,
+ Right.begin(), Right.end(), Label, false));
+}
+
+/// CheckResults - This compares the expected results to those that
+/// were actually reported. It emits any discrepencies. Return "true" if there
+/// were problems. Return "false" otherwise.
+///
+static unsigned CheckResults(Diagnostic &Diags, SourceManager &SourceMgr,
+ const TextDiagnosticBuffer &Buffer,
+ const DiagList &ExpectedErrors,
+ const DiagList &ExpectedWarnings,
+ const DiagList &ExpectedNotes) {
+ // We want to capture the delta between what was expected and what was
+ // seen.
+ //
+ // Expected \ Seen - set expected but not seen
+ // Seen \ Expected - set seen but not expected
+ unsigned NumProblems = 0;
+
+ // See if there are error mismatches.
+ NumProblems += CompareDiagLists(Diags, SourceMgr,
+ ExpectedErrors.begin(), ExpectedErrors.end(),
+ Buffer.err_begin(), Buffer.err_end(),
+ "error");
+
+ // See if there are warning mismatches.
+ NumProblems += CompareDiagLists(Diags, SourceMgr,
+ ExpectedWarnings.begin(),
+ ExpectedWarnings.end(),
+ Buffer.warn_begin(), Buffer.warn_end(),
+ "warning");
+
+ // See if there are note mismatches.
+ NumProblems += CompareDiagLists(Diags, SourceMgr,
+ ExpectedNotes.begin(),
+ ExpectedNotes.end(),
+ Buffer.note_begin(), Buffer.note_end(),
+ "note");
+
+ return NumProblems;
+}
+
+
+void VerifyDiagnosticsClient::CheckDiagnostics() {
+ DiagList ExpectedErrors, ExpectedWarnings, ExpectedNotes;
+
+ // Ensure any diagnostics go to the primary client.
+ DiagnosticClient *CurClient = Diags.getClient();
+ Diags.setClient(PrimaryClient.get());
+
+ // If we have a preprocessor, scan the source for expected diagnostic
+ // markers. If not then any diagnostics are unexpected.
+ if (CurrentPreprocessor) {
+ FindExpectedDiags(*CurrentPreprocessor, ExpectedErrors, ExpectedWarnings,
+ ExpectedNotes);
+
+ // Check that the expected diagnostics occurred.
+ NumErrors += CheckResults(Diags, CurrentPreprocessor->getSourceManager(),
+ *Buffer,
+ ExpectedErrors, ExpectedWarnings, ExpectedNotes);
+ } else {
+ NumErrors += (PrintProblem(Diags, 0,
+ Buffer->err_begin(), Buffer->err_end(),
+ "error", false) +
+ PrintProblem(Diags, 0,
+ Buffer->warn_begin(), Buffer->warn_end(),
+ "warn", false) +
+ PrintProblem(Diags, 0,
+ Buffer->note_begin(), Buffer->note_end(),
+ "note", false));
+ }
+
+ Diags.setClient(CurClient);
+
+ // Reset the buffer, we have processed all the diagnostics in it.
+ Buffer.reset(new TextDiagnosticBuffer());
+}
diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp
index 7b01b0fb7416..ff44c9051663 100644
--- a/lib/Frontend/Warnings.cpp
+++ b/lib/Frontend/Warnings.cpp
@@ -24,6 +24,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include <cstdio>
#include <cstring>
@@ -32,26 +33,24 @@
using namespace clang;
bool clang::ProcessWarningOptions(Diagnostic &Diags,
- std::vector<std::string> &Warnings,
- bool Pedantic, bool PedanticErrors,
- bool NoWarnings) {
+ const DiagnosticOptions &Opts) {
Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers
- Diags.setIgnoreAllWarnings(NoWarnings);
+ Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
// If -pedantic or -pedantic-errors was specified, then we want to map all
// extension diagnostics onto WARNING or ERROR unless the user has futz'd
// around with them explicitly.
- if (PedanticErrors)
+ if (Opts.PedanticErrors)
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Error);
- else if (Pedantic)
+ else if (Opts.Pedantic)
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Warn);
else
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Ignore);
// FIXME: -Wfatal-errors / -Wfatal-errors=foo
- for (unsigned i = 0, e = Warnings.size(); i != e; ++i) {
- const std::string &Opt = Warnings[i];
+ for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
+ const std::string &Opt = Opts.Warnings[i];
const char *OptStart = &Opt[0];
const char *OptEnd = OptStart+Opt.size();
assert(*OptEnd == 0 && "Expect null termination for lower-bound search");
@@ -100,8 +99,7 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags,
}
if (Diags.setDiagnosticGroupMapping(OptStart, Mapping))
- Diags.Report(FullSourceLoc(), diag::warn_unknown_warning_option)
- << ("-W" + Opt);
+ Diags.Report(diag::warn_unknown_warning_option) << ("-W" + Opt);
}
return false;
diff --git a/lib/Headers/stdint.h b/lib/Headers/stdint.h
index f03c1777ab01..bb81a6a3386a 100644
--- a/lib/Headers/stdint.h
+++ b/lib/Headers/stdint.h
@@ -33,60 +33,178 @@
# include_next <stdint.h>
#else
-/* We currently only support targets with power of two, 2s complement integers.
- */
-
/* C99 7.18.1.1 Exact-width integer types.
* C99 7.18.1.2 Minimum-width integer types.
* C99 7.18.1.3 Fastest minimum-width integer types.
- * Since we only support pow-2 targets, these map directly to exact width types.
+ *
+ * The standard requires that exact-width type be defined for 8-, 16-, 32-, and
+ * 64-bit types if they are implemented. Other exact width types are optional.
+ * This implementation defines an exact-width types for every integer width
+ * that is represented in the standard integer types.
+ *
+ * The standard also requires minimum-width types be defined for 8-, 16-, 32-,
+ * and 64-bit widths regardless of whether there are corresponding exact-width
+ * types.
+ *
+ * To accomodate targets that are missing types that are exactly 8, 16, 32, or
+ * 64 bits wide, this implementation takes an approach of cascading
+ * redefintions, redefining __int_leastN_t to successively smaller exact-width
+ * types. It is therefore important that the types are defined in order of
+ * descending widths.
+ *
+ * We currently assume that the minimum-width types and the fastest
+ * minimum-width types are the same. This is allowed by the standard, but is
+ * suboptimal.
+ *
+ * In violation of the standard, some targets do not implement a type that is
+ * wide enough to represent all of the required widths (8-, 16-, 32-, 64-bit).
+ * To accomodate these targets, a required minimum-width type is only
+ * defined if there exists an exact-width type of equal or greater width.
*/
-/* Some 16-bit targets do not have a 64-bit datatype. Only define the 64-bit
- * typedefs if there is something to typedef them to.
- */
#ifdef __INT64_TYPE__
-#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
-typedef __INT64_TYPE__ int64_t;
-#endif
+# ifndef __int8_t_defined /* glibc sys/types.h also defines int64_t*/
+typedef signed __INT64_TYPE__ int64_t;
+# endif /* __int8_t_defined */
typedef unsigned __INT64_TYPE__ uint64_t;
-typedef int64_t int_least64_t;
-typedef uint64_t uint_least64_t;
-typedef int64_t int_fast64_t;
-typedef uint64_t uint_fast64_t;
-#endif
-
-#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
-typedef __INT32_TYPE__ int32_t;
-#endif
-#ifndef __uint32_t_defined /* more glibc compatibility */
-#define __uint32_t_defined
+# define __int_least64_t int64_t
+# define __uint_least64_t uint64_t
+# define __int_least32_t int64_t
+# define __uint_least32_t uint64_t
+# define __int_least16_t int64_t
+# define __uint_least16_t uint64_t
+# define __int_least8_t int64_t
+# define __uint_least8_t uint64_t
+#endif /* __INT64_TYPE__ */
+
+#ifdef __int_least64_t
+typedef __int_least64_t int_least64_t;
+typedef __uint_least64_t uint_least64_t;
+typedef __int_least64_t int_fast64_t;
+typedef __uint_least64_t uint_fast64_t;
+#endif /* __int_least64_t */
+
+#ifdef __INT56_TYPE__
+typedef signed __INT56_TYPE__ int56_t;
+typedef unsigned __INT56_TYPE__ uint56_t;
+typedef int56_t int_least56_t;
+typedef uint56_t uint_least56_t;
+typedef int56_t int_fast56_t;
+typedef uint56_t uint_fast56_t;
+# define __int_least32_t int56_t
+# define __uint_least32_t uint56_t
+# define __int_least16_t int56_t
+# define __uint_least16_t uint56_t
+# define __int_least8_t int56_t
+# define __uint_least8_t uint56_t
+#endif /* __INT56_TYPE__ */
+
+
+#ifdef __INT48_TYPE__
+typedef signed __INT48_TYPE__ int48_t;
+typedef unsigned __INT48_TYPE__ uint48_t;
+typedef int48_t int_least48_t;
+typedef uint48_t uint_least48_t;
+typedef int48_t int_fast48_t;
+typedef uint48_t uint_fast48_t;
+# define __int_least32_t int48_t
+# define __uint_least32_t uint48_t
+# define __int_least16_t int48_t
+# define __uint_least16_t uint48_t
+# define __int_least8_t int48_t
+# define __uint_least8_t uint48_t
+#endif /* __INT48_TYPE__ */
+
+
+#ifdef __INT40_TYPE__
+typedef signed __INT40_TYPE__ int40_t;
+typedef unsigned __INT40_TYPE__ uint40_t;
+typedef int40_t int_least40_t;
+typedef uint40_t uint_least40_t;
+typedef int40_t int_fast40_t;
+typedef uint40_t uint_fast40_t;
+# define __int_least32_t int40_t
+# define __uint_least32_t uint40_t
+# define __int_least16_t int40_t
+# define __uint_least16_t uint40_t
+# define __int_least8_t int40_t
+# define __uint_least8_t uint40_t
+#endif /* __INT40_TYPE__ */
+
+
+#ifdef __INT32_TYPE__
+
+# ifndef __int8_t_defined /* glibc sys/types.h also defines int32_t*/
+typedef signed __INT32_TYPE__ int32_t;
+# endif /* __int8_t_defined */
+
+# ifndef __uint32_t_defined /* more glibc compatibility */
+# define __uint32_t_defined
typedef unsigned __INT32_TYPE__ uint32_t;
-#endif
-typedef int32_t int_least32_t;
-typedef uint32_t uint_least32_t;
-typedef int32_t int_fast32_t;
-typedef uint32_t uint_fast32_t;
-
-
-#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
-typedef __INT16_TYPE__ int16_t;
-#endif
+# endif /* __uint32_t_defined */
+
+# define __int_least32_t int32_t
+# define __uint_least32_t uint32_t
+# define __int_least16_t int32_t
+# define __uint_least16_t uint32_t
+# define __int_least8_t int32_t
+# define __uint_least8_t uint32_t
+#endif /* __INT32_TYPE__ */
+
+#ifdef __int_least32_t
+typedef __int_least32_t int_least32_t;
+typedef __uint_least32_t uint_least32_t;
+typedef __int_least32_t int_fast32_t;
+typedef __uint_least32_t uint_fast32_t;
+#endif /* __int_least32_t */
+
+#ifdef __INT24_TYPE__
+typedef signed __INT24_TYPE__ int24_t;
+typedef unsigned __INT24_TYPE__ uint24_t;
+typedef int24_t int_least24_t;
+typedef uint24_t uint_least24_t;
+typedef int24_t int_fast24_t;
+typedef uint24_t uint_fast24_t;
+# define __int_least16_t int24_t
+# define __uint_least16_t uint24_t
+# define __int_least8_t int24_t
+# define __uint_least8_t uint24_t
+#endif /* __INT24_TYPE__ */
+
+#ifdef __INT16_TYPE__
+#ifndef __int8_t_defined /* glibc sys/types.h also defines int16_t*/
+typedef signed __INT16_TYPE__ int16_t;
+#endif /* __int8_t_defined */
typedef unsigned __INT16_TYPE__ uint16_t;
-typedef int16_t int_least16_t;
-typedef uint16_t uint_least16_t;
-typedef int16_t int_fast16_t;
-typedef uint16_t uint_fast16_t;
-
-
-#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
+# define __int_least16_t int16_t
+# define __uint_least16_t uint16_t
+# define __int_least8_t int16_t
+# define __uint_least8_t uint16_t
+#endif /* __INT16_TYPE__ */
+
+#ifdef __int_least16_t
+typedef __int_least16_t int_least16_t;
+typedef __uint_least16_t uint_least16_t;
+typedef __int_least16_t int_fast16_t;
+typedef __uint_least16_t uint_fast16_t;
+#endif /* __int_least16_t */
+
+
+#ifdef __INT8_TYPE__
+#ifndef __int8_t_defined /* glibc sys/types.h also defines int8_t*/
typedef signed __INT8_TYPE__ int8_t;
-#endif
+#endif /* __int8_t_defined */
typedef unsigned __INT8_TYPE__ uint8_t;
-typedef int8_t int_least8_t;
-typedef uint8_t uint_least8_t;
-typedef int8_t int_fast8_t;
-typedef uint8_t uint_fast8_t;
+# define __int_least8_t int8_t
+# define __uint_least8_t uint8_t
+#endif /* __INT8_TYPE__ */
+
+#ifdef __int_least8_t
+typedef __int_least8_t int_least8_t;
+typedef __uint_least8_t uint_least8_t;
+typedef __int_least8_t int_fast8_t;
+typedef __uint_least8_t uint_fast8_t;
+#endif /* __int_least8_t */
/* prevent glibc sys/types.h from defining conflicting types */
#ifndef __int8_t_defined
@@ -108,75 +226,376 @@ typedef __UINTMAX_TYPE__ uintmax_t;
/* C99 7.18.4 Macros for minimum-width integer constants.
*
+ * The standard requires that integer constant macros be defined for all the
+ * minimum-width types defined above. As 8-, 16-, 32-, and 64-bit minimum-width
+ * types are required, the corresponding integer constant macros are defined
+ * here. This implementation also defines minimum-width types for every other
+ * integer width that the target implements, so corresponding macros are
+ * defined below, too.
+ *
+ * These macros are defined using the same successive-shrinking approach as
+ * the type definitions above. It is likewise important that macros are defined
+ * in order of decending width.
+ *
* Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the
* claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
*/
-/* Only define the 64-bit size macros if we have 64-bit support. */
+#define __int_c_join(a, b) a ## b
+#define __int_c(v, suffix) __int_c_join(v, suffix)
+#define __uint_c(v, suffix) __int_c_join(v##U, suffix)
+
+
#ifdef __INT64_TYPE__
-#define INT64_C(v) (v##LL)
-#define UINT64_C(v) (v##ULL)
-#endif
+# ifdef __INT64_C_SUFFIX__
+# define __int64_c_suffix __INT64_C_SUFFIX__
+# define __int32_c_suffix __INT64_C_SUFFIX__
+# define __int16_c_suffix __INT64_C_SUFFIX__
+# define __int8_c_suffix __INT64_C_SUFFIX__
+# else
+# undef __int64_c_suffix
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT64_C_SUFFIX__ */
+#endif /* __INT64_TYPE__ */
+
+#ifdef __int_least64_t
+# ifdef __int64_c_suffix
+# define INT64_C(v) __int_c(v, __int64_c_suffix)
+# define UINT64_C(v) __uint_c(v, __int64_c_suffix)
+# else
+# define INT64_C(v) v
+# define UINT64_C(v) v ## U
+# endif /* __int64_c_suffix */
+#endif /* __int_least64_t */
+
+
+#ifdef __INT56_TYPE__
+# ifdef __INT56_C_SUFFIX__
+# define INT56_C(v) __int_c(v, __INT56_C_SUFFIX__)
+# define UINT56_C(v) __uint_c(v, __INT56_C_SUFFIX__)
+# define __int32_c_suffix __INT56_C_SUFFIX__
+# define __int16_c_suffix __INT56_C_SUFFIX__
+# define __int8_c_suffix __INT56_C_SUFFIX__
+# else
+# define INT56_C(v) v
+# define UINT56_C(v) v ## U
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT56_C_SUFFIX__ */
+#endif /* __INT56_TYPE__ */
+
+
+#ifdef __INT48_TYPE__
+# ifdef __INT48_C_SUFFIX__
+# define INT48_C(v) __int_c(v, __INT48_C_SUFFIX__)
+# define UINT48_C(v) __uint_c(v, __INT48_C_SUFFIX__)
+# define __int32_c_suffix __INT48_C_SUFFIX__
+# define __int16_c_suffix __INT48_C_SUFFIX__
+# define __int8_c_suffix __INT48_C_SUFFIX__
+# else
+# define INT48_C(v) v
+# define UINT48_C(v) v ## U
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT48_C_SUFFIX__ */
+#endif /* __INT48_TYPE__ */
+
+
+#ifdef __INT40_TYPE__
+# ifdef __INT40_C_SUFFIX__
+# define INT40_C(v) __int_c(v, __INT40_C_SUFFIX__)
+# define UINT40_C(v) __uint_c(v, __INT40_C_SUFFIX__)
+# define __int32_c_suffix __INT40_C_SUFFIX__
+# define __int16_c_suffix __INT40_C_SUFFIX__
+# define __int8_c_suffix __INT40_C_SUFFIX__
+# else
+# define INT40_C(v) v
+# define UINT40_C(v) v ## U
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT40_C_SUFFIX__ */
+#endif /* __INT40_TYPE__ */
+
+
+#ifdef __INT32_TYPE__
+# ifdef __INT32_C_SUFFIX__
+# define __int32_c_suffix __INT32_C_SUFFIX__
+# define __int16_c_suffix __INT32_C_SUFFIX__
+# define __int8_c_suffix __INT32_C_SUFFIX__
+#else
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT32_C_SUFFIX__ */
+#endif /* __INT32_TYPE__ */
+
+#ifdef __int_least32_t
+# ifdef __int32_c_suffix
+# define INT32_C(v) __int_c(v, __int32_c_suffix)
+# define UINT32_C(v) __uint_c(v, __int32_c_suffix)
+# else
+# define INT32_C(v) v
+# define UINT32_C(v) v ## U
+# endif /* __int32_c_suffix */
+#endif /* __int_least32_t */
+
+
+#ifdef __INT24_TYPE__
+# ifdef __INT24_C_SUFFIX__
+# define INT24_C(v) __int_c(v, __INT24_C_SUFFIX__)
+# define UINT24_C(v) __uint_c(v, __INT24_C_SUFFIX__)
+# define __int16_c_suffix __INT24_C_SUFFIX__
+# define __int8_c_suffix __INT24_C_SUFFIX__
+# else
+# define INT24_C(v) v
+# define UINT24_C(v) v ## U
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT24_C_SUFFIX__ */
+#endif /* __INT24_TYPE__ */
+
+
+#ifdef __INT16_TYPE__
+# ifdef __INT16_C_SUFFIX__
+# define __int16_c_suffix __INT16_C_SUFFIX__
+# define __int8_c_suffix __INT16_C_SUFFIX__
+#else
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT16_C_SUFFIX__ */
+#endif /* __INT16_TYPE__ */
+
+#ifdef __int_least16_t
+# ifdef __int16_c_suffix
+# define INT16_C(v) __int_c(v, __int16_c_suffix)
+# define UINT16_C(v) __uint_c(v, __int16_c_suffix)
+# else
+# define INT16_C(v) v
+# define UINT16_C(v) v ## U
+# endif /* __int16_c_suffix */
+#endif /* __int_least16_t */
+
+
+#ifdef __INT8_TYPE__
+# ifdef __INT8_C_SUFFIX__
+# define __int8_c_suffix __INT8_C_SUFFIX__
+#else
+# undef __int8_c_suffix
+# endif /* __INT8_C_SUFFIX__ */
+#endif /* __INT8_TYPE__ */
+
+#ifdef __int_least8_t
+# ifdef __int8_c_suffix
+# define INT8_C(v) __int_c(v, __int8_c_suffix)
+# define UINT8_C(v) __uint_c(v, __int8_c_suffix)
+# else
+# define INT8_C(v) v
+# define UINT8_C(v) v ## U
+# endif /* __int8_c_suffix */
+#endif /* __int_least8_t */
-#define INT32_C(v) (v)
-#define UINT32_C(v) (v##U)
-#define INT16_C(v) (v)
-#define UINT16_C(v) (v##U)
-#define INT8_C(v) (v)
-#define UINT8_C(v) (v##U)
/* C99 7.18.2.1 Limits of exact-width integer types.
- * Fixed sized values have fixed size max/min.
* C99 7.18.2.2 Limits of minimum-width integer types.
- * Since we map these directly onto fixed-sized types, these values the same.
* C99 7.18.2.3 Limits of fastest minimum-width integer types.
*
+ * The presence of limit macros are completely optional in C99. This
+ * implementation defines limits for all of the types (exact- and
+ * minimum-width) that it defines above, using the limits of the minimum-width
+ * type for any types that do not have exact-width representations.
+ *
+ * As in the type definitions, this section takes an approach of
+ * successive-shrinking to determine which limits to use for the standard (8,
+ * 16, 32, 64) bit widths when they don't have exact representations. It is
+ * therefore important that the defintions be kept in order of decending
+ * widths.
+ *
* Note that C++ should not check __STDC_LIMIT_MACROS here, contrary to the
* claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
*/
-/* If we do not have 64-bit support, don't define the 64-bit size macros. */
#ifdef __INT64_TYPE__
-#define INT64_MAX 9223372036854775807LL
-#define INT64_MIN (-9223372036854775807LL-1)
-#define UINT64_MAX 18446744073709551615ULL
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-#endif
-
-#define INT32_MAX 2147483647
-#define INT32_MIN (-2147483647-1)
-#define UINT32_MAX 4294967295U
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-
-#define INT16_MAX 32767
-#define INT16_MIN (-32768)
-#define UINT16_MAX 65535
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-
-#define INT8_MAX 127
-#define INT8_MIN (-128)
-#define UINT8_MAX 255
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define UINT_FAST8_MAX UINT8_MAX
+# define INT64_MAX INT64_C( 9223372036854775807)
+# define INT64_MIN (-INT64_C( 9223372036854775807)-1)
+# define UINT64_MAX UINT64_C(18446744073709551615)
+# define __INT_LEAST64_MIN INT64_MIN
+# define __INT_LEAST64_MAX INT64_MAX
+# define __UINT_LEAST64_MAX UINT64_MAX
+# define __INT_LEAST32_MIN INT64_MIN
+# define __INT_LEAST32_MAX INT64_MAX
+# define __UINT_LEAST32_MAX UINT64_MAX
+# define __INT_LEAST16_MIN INT64_MIN
+# define __INT_LEAST16_MAX INT64_MAX
+# define __UINT_LEAST16_MAX UINT64_MAX
+# define __INT_LEAST8_MIN INT64_MIN
+# define __INT_LEAST8_MAX INT64_MAX
+# define __UINT_LEAST8_MAX UINT64_MAX
+#endif /* __INT64_TYPE__ */
+
+#ifdef __INT_LEAST64_MIN
+# define INT_LEAST64_MIN __INT_LEAST64_MIN
+# define INT_LEAST64_MAX __INT_LEAST64_MAX
+# define UINT_LEAST64_MAX __UINT_LEAST64_MAX
+# define INT_FAST64_MIN __INT_LEAST64_MIN
+# define INT_FAST64_MAX __INT_LEAST64_MAX
+# define UINT_FAST64_MAX __UINT_LEAST64_MAX
+#endif /* __INT_LEAST64_MIN */
+
+
+#ifdef __INT56_TYPE__
+# define INT56_MAX INT56_C(36028797018963967)
+# define INT56_MIN (-INT56_C(36028797018963967)-1)
+# define UINT56_MAX UINT56_C(72057594037927935)
+# define INT_LEAST56_MIN INT56_MIN
+# define INT_LEAST56_MAX INT56_MAX
+# define UINT_LEAST56_MAX UINT56_MAX
+# define INT_FAST56_MIN INT56_MIN
+# define INT_FAST56_MAX INT56_MAX
+# define UINT_FAST56_MAX UINT56_MAX
+# define __INT_LEAST32_MIN INT56_MIN
+# define __INT_LEAST32_MAX INT56_MAX
+# define __UINT_LEAST32_MAX UINT56_MAX
+# define __INT_LEAST16_MIN INT56_MIN
+# define __INT_LEAST16_MAX INT56_MAX
+# define __UINT_LEAST16_MAX UINT56_MAX
+# define __INT_LEAST8_MIN INT56_MIN
+# define __INT_LEAST8_MAX INT56_MAX
+# define __UINT_LEAST8_MAX UINT56_MAX
+#endif /* __INT56_TYPE__ */
+
+
+#ifdef __INT48_TYPE__
+# define INT48_MAX INT48_C(140737488355327)
+# define INT48_MIN (-INT48_C(140737488355327)-1)
+# define UINT48_MAX UINT48_C(281474976710655)
+# define INT_LEAST48_MIN INT48_MIN
+# define INT_LEAST48_MAX INT48_MAX
+# define UINT_LEAST48_MAX UINT48_MAX
+# define INT_FAST48_MIN INT48_MIN
+# define INT_FAST48_MAX INT48_MAX
+# define UINT_FAST48_MAX UINT48_MAX
+# define __INT_LEAST32_MIN INT48_MIN
+# define __INT_LEAST32_MAX INT48_MAX
+# define __UINT_LEAST32_MAX UINT48_MAX
+# define __INT_LEAST16_MIN INT48_MIN
+# define __INT_LEAST16_MAX INT48_MAX
+# define __UINT_LEAST16_MAX UINT48_MAX
+# define __INT_LEAST8_MIN INT48_MIN
+# define __INT_LEAST8_MAX INT48_MAX
+# define __UINT_LEAST8_MAX UINT48_MAX
+#endif /* __INT48_TYPE__ */
+
+
+#ifdef __INT40_TYPE__
+# define INT40_MAX INT40_C(549755813887)
+# define INT40_MIN (-INT40_C(549755813887)-1)
+# define UINT40_MAX UINT40_C(1099511627775)
+# define INT_LEAST40_MIN INT40_MIN
+# define INT_LEAST40_MAX INT40_MAX
+# define UINT_LEAST40_MAX UINT40_MAX
+# define INT_FAST40_MIN INT40_MIN
+# define INT_FAST40_MAX INT40_MAX
+# define UINT_FAST40_MAX UINT40_MAX
+# define __INT_LEAST32_MIN INT40_MIN
+# define __INT_LEAST32_MAX INT40_MAX
+# define __UINT_LEAST32_MAX UINT40_MAX
+# define __INT_LEAST16_MIN INT40_MIN
+# define __INT_LEAST16_MAX INT40_MAX
+# define __UINT_LEAST16_MAX UINT40_MAX
+# define __INT_LEAST8_MIN INT40_MIN
+# define __INT_LEAST8_MAX INT40_MAX
+# define __UINT_LEAST8_MAX UINT40_MAX
+#endif /* __INT40_TYPE__ */
+
+
+#ifdef __INT32_TYPE__
+# define INT32_MAX INT32_C(2147483647)
+# define INT32_MIN (-INT32_C(2147483647)-1)
+# define UINT32_MAX UINT32_C(4294967295)
+# define __INT_LEAST32_MIN INT32_MIN
+# define __INT_LEAST32_MAX INT32_MAX
+# define __UINT_LEAST32_MAX UINT32_MAX
+# define __INT_LEAST16_MIN INT32_MIN
+# define __INT_LEAST16_MAX INT32_MAX
+# define __UINT_LEAST16_MAX UINT32_MAX
+# define __INT_LEAST8_MIN INT32_MIN
+# define __INT_LEAST8_MAX INT32_MAX
+# define __UINT_LEAST8_MAX UINT32_MAX
+#endif /* __INT32_TYPE__ */
+
+#ifdef __INT_LEAST32_MIN
+# define INT_LEAST32_MIN __INT_LEAST32_MIN
+# define INT_LEAST32_MAX __INT_LEAST32_MAX
+# define UINT_LEAST32_MAX __UINT_LEAST32_MAX
+# define INT_FAST32_MIN __INT_LEAST32_MIN
+# define INT_FAST32_MAX __INT_LEAST32_MAX
+# define UINT_FAST32_MAX __UINT_LEAST32_MAX
+#endif /* __INT_LEAST32_MIN */
+
+
+#ifdef __INT24_TYPE__
+# define INT24_MAX INT24_C(8388607)
+# define INT24_MIN (-INT24_C(8388607)-1)
+# define UINT24_MAX UINT24_C(16777215)
+# define INT_LEAST24_MIN INT24_MIN
+# define INT_LEAST24_MAX INT24_MAX
+# define UINT_LEAST24_MAX UINT24_MAX
+# define INT_FAST24_MIN INT24_MIN
+# define INT_FAST24_MAX INT24_MAX
+# define UINT_FAST24_MAX UINT24_MAX
+# define __INT_LEAST16_MIN INT24_MIN
+# define __INT_LEAST16_MAX INT24_MAX
+# define __UINT_LEAST16_MAX UINT24_MAX
+# define __INT_LEAST8_MIN INT24_MIN
+# define __INT_LEAST8_MAX INT24_MAX
+# define __UINT_LEAST8_MAX UINT24_MAX
+#endif /* __INT24_TYPE__ */
+
+
+#ifdef __INT16_TYPE__
+#define INT16_MAX INT16_C(32767)
+#define INT16_MIN (-INT16_C(32767)-1)
+#define UINT16_MAX UINT16_C(65535)
+# define __INT_LEAST16_MIN INT16_MIN
+# define __INT_LEAST16_MAX INT16_MAX
+# define __UINT_LEAST16_MAX UINT16_MAX
+# define __INT_LEAST8_MIN INT16_MIN
+# define __INT_LEAST8_MAX INT16_MAX
+# define __UINT_LEAST8_MAX UINT16_MAX
+#endif /* __INT16_TYPE__ */
+
+#ifdef __INT_LEAST16_MIN
+# define INT_LEAST16_MIN __INT_LEAST16_MIN
+# define INT_LEAST16_MAX __INT_LEAST16_MAX
+# define UINT_LEAST16_MAX __UINT_LEAST16_MAX
+# define INT_FAST16_MIN __INT_LEAST16_MIN
+# define INT_FAST16_MAX __INT_LEAST16_MAX
+# define UINT_FAST16_MAX __UINT_LEAST16_MAX
+#endif /* __INT_LEAST16_MIN */
+
+
+#ifdef __INT8_TYPE__
+# define INT8_MAX INT8_C(127)
+# define INT8_MIN (-INT8_C(127)-1)
+# define UINT8_MAX UINT8_C(255)
+# define __INT_LEAST8_MIN INT8_MIN
+# define __INT_LEAST8_MAX INT8_MAX
+# define __UINT_LEAST8_MAX UINT8_MAX
+#endif /* __INT8_TYPE__ */
+
+#ifdef __INT_LEAST8_MIN
+# define INT_LEAST8_MIN __INT_LEAST8_MIN
+# define INT_LEAST8_MAX __INT_LEAST8_MAX
+# define UINT_LEAST8_MAX __UINT_LEAST8_MAX
+# define INT_FAST8_MIN __INT_LEAST8_MIN
+# define INT_FAST8_MAX __INT_LEAST8_MAX
+# define UINT_FAST8_MAX __UINT_LEAST8_MAX
+#endif /* __INT_LEAST8_MIN */
/* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */
/* C99 7.18.3 Limits of other integer types. */
@@ -234,8 +653,8 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#endif
/* 7.18.4.2 Macros for greatest-width integer constants. */
-#define INTMAX_C(v) (v##LL)
-#define UINTMAX_C(v) (v##ULL)
+#define INTMAX_C(v) v##LL
+#define UINTMAX_C(v) v##ULL
#endif /* __STDC_HOSTED__ */
#endif /* __CLANG_STDINT_H */
diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp
index 73b584b5205d..ed905f364f0d 100644
--- a/lib/Index/ResolveLocation.cpp
+++ b/lib/Index/ResolveLocation.cpp
@@ -112,6 +112,7 @@ public:
ASTLocation VisitDeclaratorDecl(DeclaratorDecl *D);
ASTLocation VisitVarDecl(VarDecl *D);
ASTLocation VisitFunctionDecl(FunctionDecl *D);
+ ASTLocation VisitObjCClassDecl(ObjCClassDecl *D);
ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
ASTLocation VisitTypedefDecl(TypedefDecl *D);
ASTLocation VisitDecl(Decl *D);
@@ -327,6 +328,17 @@ ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
return ASTLocation(D);
}
+ASTLocation DeclLocResolver::VisitObjCClassDecl(ObjCClassDecl *D) {
+ assert(ContainsLocation(D) &&
+ "Should visit only after verifying that loc is in range");
+
+ for (ObjCClassDecl::iterator I = D->begin(), E = D->end() ; I != E; ++I) {
+ if (CheckRange(I->getLocation()) == ContainsLoc)
+ return ASTLocation(D, I->getInterface(), I->getLocation());
+ }
+ return ASTLocation(D);
+}
+
ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
assert(ContainsLocation(D) &&
"Should visit only after verifying that loc is in range");
@@ -484,7 +496,7 @@ ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
assert(ContainsLocation(DInfo) &&
"Should visit only after verifying that loc is in range");
- TypeLocResolver(Ctx, Loc, D);
+ (void)TypeLocResolver(Ctx, Loc, D);
for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
if (ContainsLocation(TL))
return TypeLocResolver(Ctx, Loc, D).Visit(TL);
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index c8b9a5d5420a..f4a44324106a 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -384,10 +384,10 @@ static inline bool isNumberBody(unsigned char c) {
/// lexer buffer was all instantiated at a single point, perform the mapping.
/// This is currently only used for _Pragma implementation, so it is the slow
/// path of the hot getSourceLocation method. Do not allow it to be inlined.
-static SourceLocation GetMappedTokenLoc(Preprocessor &PP,
- SourceLocation FileLoc,
- unsigned CharNo,
- unsigned TokLen) DISABLE_INLINE;
+static DISABLE_INLINE SourceLocation GetMappedTokenLoc(Preprocessor &PP,
+ SourceLocation FileLoc,
+ unsigned CharNo,
+ unsigned TokLen);
static SourceLocation GetMappedTokenLoc(Preprocessor &PP,
SourceLocation FileLoc,
unsigned CharNo, unsigned TokLen) {
diff --git a/lib/Lex/PPCaching.cpp b/lib/Lex/PPCaching.cpp
index c3f0eeab5848..7c3780ffc0ac 100644
--- a/lib/Lex/PPCaching.cpp
+++ b/lib/Lex/PPCaching.cpp
@@ -109,6 +109,4 @@ void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) {
return;
}
}
-
- assert(0&&"Didn't find the first token represented by the annotation token!");
}
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index a74396c3146c..b54dfe093b2c 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -228,7 +228,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
return true; // A diagnostic was already emitted.
// Character literals are always int or wchar_t, expand to intmax_t.
- TargetInfo &TI = PP.getTargetInfo();
+ const TargetInfo &TI = PP.getTargetInfo();
unsigned NumBits;
if (Literal.isMultiChar())
NumBits = TI.getIntWidth();
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index f17a5d93a91a..d6a73cc74f6a 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PTHManager.h"
@@ -407,27 +408,17 @@ PTHManager::~PTHManager() {
free(PerIDCache);
}
-static void InvalidPTH(Diagnostic *Diags, Diagnostic::Level level,
- const char* Msg = 0) {
- if (!Diags) return;
- if (!Msg) Msg = "Invalid or corrupted PTH file";
- unsigned DiagID = Diags->getCustomDiagID(level, Msg);
- Diags->Report(FullSourceLoc(), DiagID);
+static void InvalidPTH(Diagnostic &Diags, const char *Msg) {
+ Diags.Report(Diags.getCustomDiagID(Diagnostic::Error, Msg));
}
-PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
- Diagnostic::Level level) {
+PTHManager* PTHManager::Create(const std::string& file, Diagnostic &Diags) {
// Memory map the PTH file.
llvm::OwningPtr<llvm::MemoryBuffer>
File(llvm::MemoryBuffer::getFile(file.c_str()));
if (!File) {
- if (Diags) {
- unsigned DiagID = Diags->getCustomDiagID(level,
- "PTH file %0 could not be read");
- Diags->Report(FullSourceLoc(), DiagID) << file;
- }
-
+ Diags.Report(diag::err_invalid_pth_file) << file;
return 0;
}
@@ -439,7 +430,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
// Check the prologue of the file.
if ((BufEnd - BufBeg) < (signed) (sizeof("cfe-pth") + 3 + 4) ||
memcmp(BufBeg, "cfe-pth", sizeof("cfe-pth") - 1) != 0) {
- InvalidPTH(Diags, level);
+ Diags.Report(diag::err_invalid_pth_file) << file;
return 0;
}
@@ -447,8 +438,8 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
const unsigned char *p = BufBeg + (sizeof("cfe-pth") - 1);
unsigned Version = ReadLE32(p);
- if (Version != PTHManager::Version) {
- InvalidPTH(Diags, level,
+ if (Version < PTHManager::Version) {
+ InvalidPTH(Diags,
Version < PTHManager::Version
? "PTH file uses an older PTH format that is no longer supported"
: "PTH file uses a newer PTH format that cannot be read");
@@ -459,7 +450,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
const unsigned char *PrologueOffset = p;
if (PrologueOffset >= BufEnd) {
- InvalidPTH(Diags, level);
+ Diags.Report(diag::err_invalid_pth_file) << file;
return 0;
}
@@ -469,7 +460,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
const unsigned char* FileTable = BufBeg + ReadLE32(FileTableOffset);
if (!(FileTable > BufBeg && FileTable < BufEnd)) {
- InvalidPTH(Diags, level);
+ Diags.Report(diag::err_invalid_pth_file) << file;
return 0; // FIXME: Proper error diagnostic?
}
@@ -478,7 +469,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
// Warn if the PTH file is empty. We still want to create a PTHManager
// as the PTH could be used with -include-pth.
if (FL->isEmpty())
- InvalidPTH(Diags, level, "PTH file contains no cached source data");
+ InvalidPTH(Diags, "PTH file contains no cached source data");
// Get the location of the table mapping from persistent ids to the
// data needed to reconstruct identifiers.
@@ -486,7 +477,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
const unsigned char* IData = BufBeg + ReadLE32(IDTableOffset);
if (!(IData >= BufBeg && IData < BufEnd)) {
- InvalidPTH(Diags, level);
+ Diags.Report(diag::err_invalid_pth_file) << file;
return 0;
}
@@ -495,7 +486,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
const unsigned char* StringIdTableOffset = PrologueOffset + sizeof(uint32_t)*1;
const unsigned char* StringIdTable = BufBeg + ReadLE32(StringIdTableOffset);
if (!(StringIdTable >= BufBeg && StringIdTable < BufEnd)) {
- InvalidPTH(Diags, level);
+ Diags.Report(diag::err_invalid_pth_file) << file;
return 0;
}
@@ -506,7 +497,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
const unsigned char* spellingBaseOffset = PrologueOffset + sizeof(uint32_t)*3;
const unsigned char* spellingBase = BufBeg + ReadLE32(spellingBaseOffset);
if (!(spellingBase >= BufBeg && spellingBase < BufEnd)) {
- InvalidPTH(Diags, level);
+ Diags.Report(diag::err_invalid_pth_file) << file;
return 0;
}
@@ -521,8 +512,7 @@ PTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags,
if (NumIds) {
PerIDCache = (IdentifierInfo**)calloc(NumIds, sizeof(*PerIDCache));
if (!PerIDCache) {
- InvalidPTH(Diags, level,
- "Could not allocate memory for processing PTH file");
+ InvalidPTH(Diags, "Could not allocate memory for processing PTH file");
return 0;
}
}
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 487b9d63c169..066909475fe3 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -44,14 +44,16 @@ using namespace clang;
//===----------------------------------------------------------------------===//
Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
- TargetInfo &target, SourceManager &SM,
+ const TargetInfo &target, SourceManager &SM,
HeaderSearch &Headers,
- IdentifierInfoLookup* IILookup)
+ IdentifierInfoLookup* IILookup,
+ bool OwnsHeaders)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
SourceMgr(SM), HeaderInfo(Headers), Identifiers(opts, IILookup),
BuiltinInfo(Target), CurPPLexer(0), CurDirLookup(0), Callbacks(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
CounterValue = 0; // __COUNTER__ starts at 0.
+ OwnsHeaderSearch = OwnsHeaders;
// Clear stats.
NumDirectives = NumDefined = NumUndefined = NumPragma = 0;
@@ -115,6 +117,10 @@ Preprocessor::~Preprocessor() {
// Delete the scratch buffer info.
delete ScratchBuf;
+ // Delete the header search info, if we own it.
+ if (OwnsHeaderSearch)
+ delete &HeaderInfo;
+
delete Callbacks;
}
@@ -186,13 +192,14 @@ void Preprocessor::PrintStats() {
// Token Spelling
//===----------------------------------------------------------------------===//
-
/// getSpelling() - Return the 'spelling' of this token. The spelling of a
/// token are the characters used to represent the token in the source file
/// after trigraph expansion and escaped-newline folding. In particular, this
/// wants to get the true, uncanonicalized, spelling of things like digraphs
/// UCNs, etc.
-std::string Preprocessor::getSpelling(const Token &Tok) const {
+std::string Preprocessor::getSpelling(const Token &Tok,
+ const SourceManager &SourceMgr,
+ const LangOptions &Features) {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
// If this token contains nothing interesting, return it directly.
@@ -215,6 +222,15 @@ std::string Preprocessor::getSpelling(const Token &Tok) const {
return Result;
}
+/// getSpelling() - Return the 'spelling' of this token. The spelling of a
+/// token are the characters used to represent the token in the source file
+/// after trigraph expansion and escaped-newline folding. In particular, this
+/// wants to get the true, uncanonicalized, spelling of things like digraphs
+/// UCNs, etc.
+std::string Preprocessor::getSpelling(const Token &Tok) const {
+ return getSpelling(Tok, SourceMgr, Features);
+}
+
/// getSpelling - This method is used to get the spelling of a token into a
/// preallocated buffer, instead of as an std::string. The caller is required
/// to allocate enough space for the token, which is guaranteed to be at least
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 344ce9e90e55..dde4bc866ac5 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -59,6 +59,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("mode", AT_mode)
.Case("used", AT_used)
.Case("alias", AT_alias)
+ .Case("cdecl", AT_cdecl)
.Case("const", AT_const)
.Case("packed", AT_packed)
.Case("malloc", AT_malloc)
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 0a4e036e4399..f00f33fcb948 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Template.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
@@ -26,6 +27,15 @@ static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
}
+
+void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id annotation?");
+ Kind = IK_TemplateId;
+ this->TemplateId = TemplateId;
+ StartLocation = TemplateId->TemplateNameLoc;
+ EndLocation = TemplateId->RAngleLoc;
+}
+
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index bf05b2baccd4..7681eac6ed8a 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -49,7 +49,8 @@ Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName) {
+ bool IsTypeName,
+ SourceLocation TypenameLoc) {
// FIXME: Parser seems to assume that Action::ActOn* takes ownership over
// passed AttributeList, however other actions don't free it, is it
@@ -213,7 +214,9 @@ MinimalAction::ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
/// Scope will always be top level file scope.
Action::DeclPtrTy
MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
- IdentifierInfo **IdentList, unsigned NumElts) {
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ unsigned NumElts) {
for (unsigned i = 0; i != NumElts; ++i) {
// Allocate and add the 'TypeNameInfo' "decl".
getTable(TypeNameInfoTablePtr)->AddEntry(true, IdentList[i]);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 99752b59507f..2bfda30a951b 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "ExtensionRAIIObject.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 154c2923486e..914bfc9db89d 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -16,6 +16,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "ExtensionRAIIObject.h"
using namespace clang;
@@ -282,11 +283,13 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
CXXScopeSpec SS;
+ SourceLocation TypenameLoc;
bool IsTypeName;
// Ignore optional 'typename'.
// FIXME: This is wrong; we should parse this as a typename-specifier.
if (Tok.is(tok::kw_typename)) {
+ TypenameLoc = Tok.getLocation();
ConsumeToken();
IsTypeName = true;
}
@@ -329,7 +332,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
tok::semi);
return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
- AttrList, IsTypeName);
+ AttrList, IsTypeName, TypenameLoc);
}
/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
@@ -586,13 +589,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Eat the template argument list and try to continue parsing this as
// a class (or template thereof).
TemplateArgList TemplateArgs;
- TemplateArgIsTypeList TemplateArgIsType;
- TemplateArgLocationList TemplateArgLocations;
SourceLocation LAngleLoc, RAngleLoc;
if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
true, LAngleLoc,
- TemplateArgs, TemplateArgIsType,
- TemplateArgLocations, RAngleLoc)) {
+ TemplateArgs, RAngleLoc)) {
// We couldn't parse the template argument list at all, so don't
// try to give any location information for the list.
LAngleLoc = RAngleLoc = SourceLocation();
@@ -704,7 +704,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// or explicit instantiation.
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Action::TUK_Declaration) {
@@ -720,7 +719,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc,
Attr);
} else if (TUK == Action::TUK_Reference) {
@@ -729,7 +727,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK,
@@ -777,7 +774,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc,
Attr,
Action::MultiTemplateParamsArg(Actions,
@@ -1304,7 +1300,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
- Diag(Tok, diag::ext_extra_struct_semi);
+ Diag(Tok, diag::ext_extra_struct_semi)
+ << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
ConsumeToken();
continue;
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index a00dfb0b4c36..b2ecc9e827f1 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -108,52 +109,43 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (!HasScopeSpecifier && !ObjectType)
break;
+ TentativeParsingAction TPA(*this);
SourceLocation TemplateKWLoc = ConsumeToken();
UnqualifiedId TemplateName;
if (Tok.is(tok::identifier)) {
- TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
-
- // If the next token is not '<', we may have a stray 'template' keyword.
- // Complain and suggest removing the template keyword, but otherwise
- // allow parsing to continue.
- if (NextToken().isNot(tok::less)) {
- Diag(NextToken().getLocation(),
- diag::err_less_after_template_name_in_nested_name_spec)
- << Tok.getIdentifierInfo()->getName()
- << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc));
- break;
- }
-
// Consume the identifier.
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
} else if (Tok.is(tok::kw_operator)) {
if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
- TemplateName))
+ TemplateName)) {
+ TPA.Commit();
break;
+ }
if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) {
Diag(TemplateName.getSourceRange().getBegin(),
diag::err_id_after_template_in_nested_name_spec)
<< TemplateName.getSourceRange();
- break;
- } else if (Tok.isNot(tok::less)) {
- std::string OperatorName = "operator ";
- OperatorName += getOperatorSpelling(
- TemplateName.OperatorFunctionId.Operator);
- Diag(Tok.getLocation(),
- diag::err_less_after_template_name_in_nested_name_spec)
- << OperatorName
- << TemplateName.getSourceRange();
+ TPA.Commit();
break;
}
} else {
- Diag(Tok.getLocation(),
- diag::err_id_after_template_in_nested_name_spec)
- << SourceRange(TemplateKWLoc);
+ TPA.Revert();
break;
}
+ // If the next token is not '<', we have a qualified-id that refers
+ // to a template name, such as T::template apply, but is not a
+ // template-id.
+ if (Tok.isNot(tok::less)) {
+ TPA.Revert();
+ break;
+ }
+
+ // Commit to parsing the template-id.
+ TPA.Commit();
TemplateTy Template
= Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
ObjectType);
@@ -381,13 +373,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
OwningExprResult Result = ParseExpression();
// Match the ')'.
- if (Result.isInvalid())
- SkipUntil(tok::r_paren);
-
- if (Tok.is(tok::r_paren))
- RParenLoc = ConsumeParen();
- else
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
if (!Result.isInvalid() && !CastTy.isInvalid())
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
@@ -820,13 +806,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
- TemplateArgIsTypeList TemplateArgIsType;
- TemplateArgLocationList TemplateArgLocations;
if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
&SS, true, LAngleLoc,
TemplateArgs,
- TemplateArgIsType,
- TemplateArgLocations,
RAngleLoc))
return true;
@@ -851,15 +833,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
- void **Args = TemplateId->getTemplateArgs();
- bool *ArgIsType = TemplateId->getTemplateArgIsType();
- SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
+ ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
- Arg != ArgEnd; ++Arg) {
+ Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
- ArgIsType[Arg] = TemplateArgIsType[Arg];
- ArgLocs[Arg] = TemplateArgLocations[Arg];
- }
Id.setTemplateId(TemplateId);
return false;
@@ -867,14 +844,12 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Bundle the template arguments together.
ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
- TemplateArgIsType.data(),
TemplateArgs.size());
// Constructor and destructor names.
Action::TypeResult Type
= Actions.ActOnTemplateIdType(Template, NameLoc,
LAngleLoc, TemplateArgsPtr,
- &TemplateArgLocations[0],
RAngleLoc);
if (Type.isInvalid())
return true;
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index b043dd99f304..65bd79d6b4f2 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -61,6 +61,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ConsumeToken(); // the identifier "class"
llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
+ llvm::SmallVector<SourceLocation, 8> ClassLocs;
+
while (1) {
if (Tok.isNot(tok::identifier)) {
@@ -69,6 +71,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
return DeclPtrTy();
}
ClassNames.push_back(Tok.getIdentifierInfo());
+ ClassLocs.push_back(Tok.getLocation());
ConsumeToken();
if (Tok.isNot(tok::comma))
@@ -81,8 +84,9 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
return DeclPtrTy();
- return Actions.ActOnForwardClassDeclaration(atLoc,
- &ClassNames[0], ClassNames.size());
+ return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
+ ClassLocs.data(),
+ ClassNames.size());
}
///
@@ -123,6 +127,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
Diag(Tok, diag::err_expected_ident); // missing class or category name.
return DeclPtrTy();
}
+
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
@@ -829,6 +834,12 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
while (1) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
+ ProtocolIdents.size());
+ ConsumeToken();
+ }
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::greater);
@@ -895,7 +906,8 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
- Diag(Tok, diag::ext_extra_struct_semi);
+ Diag(Tok, diag::ext_extra_struct_semi)
+ << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
ConsumeToken();
continue;
}
@@ -982,6 +994,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
ConsumeToken(); // the "protocol" identifier
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCProtocolDecl(CurScope);
+ ConsumeToken();
+ }
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing protocol name.
return DeclPtrTy();
@@ -1092,6 +1109,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
atLoc, nameId, nameLoc, categoryId,
categoryLoc);
ObjCImpDecl = ImplCatType;
+ PendingObjCImpDecl.push_back(ObjCImpDecl);
return DeclPtrTy();
}
// We have a class implementation
@@ -1114,7 +1132,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
if (Tok.is(tok::l_brace)) // we have ivars
ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
ObjCImpDecl = ImplClsType;
-
+ PendingObjCImpDecl.push_back(ObjCImpDecl);
+
return DeclPtrTy();
}
@@ -1126,12 +1145,21 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
if (ObjCImpDecl) {
Actions.ActOnAtEnd(atLoc, ObjCImpDecl);
ObjCImpDecl = DeclPtrTy();
+ PendingObjCImpDecl.pop_back();
}
else
Diag(atLoc, diag::warn_expected_implementation); // missing @implementation
return Result;
}
+Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
+ if (PendingObjCImpDecl.empty())
+ return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
+ DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
+ Actions.ActOnAtEnd(SourceLocation(), ImpDecl);
+ return Actions.ConvertDeclToDeclGroup(ImpDecl);
+}
+
/// compatibility-alias-decl:
/// @compatibility_alias alias-name class-name ';'
///
@@ -1201,6 +1229,8 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
}
if (Tok.isNot(tok::semi))
Diag(Tok, diag::err_expected_semi_after) << "@synthesize";
+ else
+ ConsumeToken(); // consume ';'
return DeclPtrTy();
}
@@ -1406,8 +1436,10 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
// parse optional ';'
if (Tok.is(tok::semi)) {
- if (ObjCImpDecl)
- Diag(Tok, diag::warn_semicolon_before_method_nody);
+ if (ObjCImpDecl) {
+ Diag(Tok, diag::warn_semicolon_before_method_body)
+ << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ }
ConsumeToken();
}
@@ -1546,6 +1578,13 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
SourceLocation NameLoc,
IdentifierInfo *ReceiverName,
ExprArg ReceiverExpr) {
+ if (Tok.is(tok::code_completion)) {
+ if (ReceiverName)
+ Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc);
+ else
+ Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get());
+ ConsumeToken();
+ }
// Parse objc-selector
SourceLocation Loc;
IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 99578837c21c..16b1c800800f 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
@@ -484,12 +485,17 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Get the a default value, if given.
if (Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
- OwningExprResult DefaultExpr = ParseCXXIdExpression();
- if (DefaultExpr.isInvalid())
+ ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
+ if (Default.isInvalid()) {
+ Diag(Tok.getLocation(),
+ diag::err_default_template_template_parameter_not_template);
+ static tok::TokenKind EndToks[] = {
+ tok::comma, tok::greater, tok::greatergreater
+ };
+ SkipUntil(EndToks, 3, true, true);
return Param;
- else if (Param)
- Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc,
- move(DefaultExpr));
+ } else if (Param)
+ Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
}
return Param;
@@ -582,8 +588,6 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
bool ConsumeLastToken,
SourceLocation &LAngleLoc,
TemplateArgList &TemplateArgs,
- TemplateArgIsTypeList &TemplateArgIsType,
- TemplateArgLocationList &TemplateArgLocations,
SourceLocation &RAngleLoc) {
assert(Tok.is(tok::less) && "Must have already parsed the template-name");
@@ -595,8 +599,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
{
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
if (Tok.isNot(tok::greater))
- Invalid = ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType,
- TemplateArgLocations);
+ Invalid = ParseTemplateArgumentList(TemplateArgs);
if (Invalid) {
// Try to find the closing '>'.
@@ -688,14 +691,10 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
- TemplateArgIsTypeList TemplateArgIsType;
- TemplateArgLocationList TemplateArgLocations;
bool Invalid = ParseTemplateIdAfterTemplateName(Template,
TemplateNameLoc,
SS, false, LAngleLoc,
TemplateArgs,
- TemplateArgIsType,
- TemplateArgLocations,
RAngleLoc);
if (Invalid) {
@@ -707,7 +706,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
}
ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
- TemplateArgIsType.data(),
TemplateArgs.size());
// Build the annotation token.
@@ -715,7 +713,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
Action::TypeResult Type
= Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
LAngleLoc, TemplateArgsPtr,
- &TemplateArgLocations[0],
RAngleLoc);
if (Type.isInvalid()) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
@@ -751,14 +748,9 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
- void **Args = TemplateId->getTemplateArgs();
- bool *ArgIsType = TemplateId->getTemplateArgIsType();
- SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
- for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) {
+ ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
- ArgIsType[Arg] = TemplateArgIsType[Arg];
- ArgLocs[Arg] = TemplateArgLocations[Arg];
- }
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
@@ -794,7 +786,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
Action::TypeResult Type
@@ -802,7 +793,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
@@ -817,33 +807,125 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
TemplateId->Destroy();
}
+/// \brief Determine whether the given token can end a template argument.
+static bool isEndOfTemplateArgument(Token Tok) {
+ return Tok.is(tok::comma) || Tok.is(tok::greater) ||
+ Tok.is(tok::greatergreater);
+}
+
+/// \brief Parse a C++ template template argument.
+ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
+ if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
+ !Tok.is(tok::annot_cxxscope))
+ return ParsedTemplateArgument();
+
+ // C++0x [temp.arg.template]p1:
+ // A template-argument for a template template-parameter shall be the name
+ // of a class template or a template alias, expressed as id-expression.
+ //
+ // We parse an id-expression that refers to a class template or template
+ // alias. The grammar we parse is:
+ //
+ // nested-name-specifier[opt] template[opt] identifier
+ //
+ // followed by a token that terminates a template argument, such as ',',
+ // '>', or (in some cases) '>>'.
+ CXXScopeSpec SS; // nested-name-specifier, if present
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
+ /*EnteringContext=*/false);
+
+ if (SS.isSet() && Tok.is(tok::kw_template)) {
+ // Parse the optional 'template' keyword following the
+ // nested-name-specifier.
+ SourceLocation TemplateLoc = ConsumeToken();
+
+ if (Tok.is(tok::identifier)) {
+ // We appear to have a dependent template name.
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ // If the next token signals the end of a template argument,
+ // then we have a dependent template name that could be a template
+ // template argument.
+ if (isEndOfTemplateArgument(Tok)) {
+ TemplateTy Template
+ = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
+ /*ObjectType=*/0);
+ if (Template.get())
+ return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
+ }
+ } else if (Tok.is(tok::identifier)) {
+ // We may have a (non-dependent) template name.
+ TemplateTy Template;
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ if (isEndOfTemplateArgument(Tok)) {
+ TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
+ /*ObjectType=*/0,
+ /*EnteringContext=*/false,
+ Template);
+ if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+ // We have an id-expression that refers to a class template or
+ // (C++0x) template alias.
+ return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
+ }
+ }
+
+ // We don't have a template template argument.
+ return ParsedTemplateArgument();
+}
+
/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
///
/// template-argument: [C++ 14.2]
/// constant-expression
/// type-id
/// id-expression
-void *Parser::ParseTemplateArgument(bool &ArgIsType) {
+ParsedTemplateArgument Parser::ParseTemplateArgument() {
// C++ [temp.arg]p2:
// In a template-argument, an ambiguity between a type-id and an
// expression is resolved to a type-id, regardless of the form of
// the corresponding template-parameter.
//
- // Therefore, we initially try to parse a type-id.
+ // Therefore, we initially try to parse a type-id.
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
- ArgIsType = true;
+ SourceLocation Loc = Tok.getLocation();
TypeResult TypeArg = ParseTypeName();
if (TypeArg.isInvalid())
- return 0;
- return TypeArg.get();
+ return ParsedTemplateArgument();
+
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
+ Loc);
}
+
+ // Try to parse a template template argument.
+ {
+ TentativeParsingAction TPA(*this);
+ ParsedTemplateArgument TemplateTemplateArgument
+ = ParseTemplateTemplateArgument();
+ if (!TemplateTemplateArgument.isInvalid()) {
+ TPA.Commit();
+ return TemplateTemplateArgument;
+ }
+
+ // Revert this tentative parse to parse a non-type template argument.
+ TPA.Revert();
+ }
+
+ // Parse a non-type template argument.
+ SourceLocation Loc = Tok.getLocation();
OwningExprResult ExprArg = ParseConstantExpression();
if (ExprArg.isInvalid() || !ExprArg.get())
- return 0;
+ return ParsedTemplateArgument();
- ArgIsType = false;
- return ExprArg.release();
+ return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
+ ExprArg.release(), Loc);
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
@@ -853,22 +935,17 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
/// template-argument
/// template-argument-list ',' template-argument
bool
-Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
- TemplateArgIsTypeList &TemplateArgIsType,
- TemplateArgLocationList &TemplateArgLocations) {
+Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
while (true) {
- bool IsType = false;
- SourceLocation Loc = Tok.getLocation();
- void *Arg = ParseTemplateArgument(IsType);
- if (Arg) {
- TemplateArgs.push_back(Arg);
- TemplateArgIsType.push_back(IsType);
- TemplateArgLocations.push_back(Loc);
- } else {
+ ParsedTemplateArgument Arg = ParseTemplateArgument();
+ if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, true, true);
return true;
}
+ // Save this template argument.
+ TemplateArgs.push_back(Arg);
+
// If the next token is a comma, consume it and keep reading
// arguments.
if (Tok.isNot(tok::comma)) break;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 335a6cf36254..a9152745b3f7 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "llvm/Support/raw_ostream.h"
#include "ExtensionRAIIObject.h"
#include "ParsePragma.h"
diff --git a/lib/Rewrite/DeltaTree.cpp b/lib/Rewrite/DeltaTree.cpp
index a94444b50c77..101cf93f9db9 100644
--- a/lib/Rewrite/DeltaTree.cpp
+++ b/lib/Rewrite/DeltaTree.cpp
@@ -19,12 +19,6 @@ using namespace clang;
using llvm::cast;
using llvm::dyn_cast;
-namespace {
- struct SourceDelta;
- class DeltaTreeNode;
- class DeltaTreeInteriorNode;
-}
-
/// The DeltaTree class is a multiway search tree (BTree) structure with some
/// fancy features. B-Trees are are generally more memory and cache efficient
/// than binary trees, because they store multiple keys/values in each node.
@@ -55,21 +49,17 @@ namespace {
return Delta;
}
};
-} // end anonymous namespace
-
-
-namespace {
- struct InsertResult {
- DeltaTreeNode *LHS, *RHS;
- SourceDelta Split;
- };
-} // end anonymous namespace
-
-
-namespace {
+
/// DeltaTreeNode - The common part of all nodes.
///
class DeltaTreeNode {
+ public:
+ struct InsertResult {
+ DeltaTreeNode *LHS, *RHS;
+ SourceDelta Split;
+ };
+
+ private:
friend class DeltaTreeInteriorNode;
/// WidthFactor - This controls the number of K/V slots held in the BTree:
@@ -473,7 +463,7 @@ void DeltaTree::AddDelta(unsigned FileIndex, int Delta) {
assert(Delta && "Adding a noop?");
DeltaTreeNode *MyRoot = getRoot(Root);
- InsertResult InsertRes;
+ DeltaTreeNode::InsertResult InsertRes;
if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) {
Root = MyRoot = new DeltaTreeInteriorNode(InsertRes);
}
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 9b24d55f3ece..88ac4e49cf9e 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -16,28 +16,79 @@
#include "clang/Lex/Preprocessor.h"
#include "Sema.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
#include <functional>
+
using namespace clang;
+using llvm::StringRef;
//===----------------------------------------------------------------------===//
// Code completion string implementation
//===----------------------------------------------------------------------===//
-CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
- : Kind(Kind), Text(0)
+CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
+ : Kind(Kind), Text("")
{
- assert((Kind == CK_Text || Kind == CK_Placeholder || Kind == CK_Informative)
- && "Invalid text chunk kind");
- char *New = new char [std::strlen(Text) + 1];
- std::strcpy(New, Text);
- this->Text = New;
+ switch (Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter: {
+ char *New = new char [Text.size() + 1];
+ std::memcpy(New, Text.data(), Text.size());
+ New[Text.size()] = '\0';
+ this->Text = New;
+ break;
+ }
+
+ case CK_Optional:
+ llvm::llvm_unreachable("Optional strings cannot be created from text");
+ break;
+
+ case CK_LeftParen:
+ this->Text = "(";
+ break;
+
+ case CK_RightParen:
+ this->Text = ")";
+ break;
+
+ case CK_LeftBracket:
+ this->Text = "[";
+ break;
+
+ case CK_RightBracket:
+ this->Text = "]";
+ break;
+
+ case CK_LeftBrace:
+ this->Text = "{";
+ break;
+
+ case CK_RightBrace:
+ this->Text = "}";
+ break;
+
+ case CK_LeftAngle:
+ this->Text = "<";
+ break;
+
+ case CK_RightAngle:
+ this->Text = ">";
+ break;
+
+ case CK_Comma:
+ this->Text = ", ";
+ break;
+ }
}
CodeCompletionString::Chunk
-CodeCompletionString::Chunk::CreateText(const char *Text) {
+CodeCompletionString::Chunk::CreateText(StringRef Text) {
return Chunk(CK_Text, Text);
}
@@ -51,15 +102,22 @@ CodeCompletionString::Chunk::CreateOptional(
}
CodeCompletionString::Chunk
-CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
+CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
return Chunk(CK_Placeholder, Placeholder);
}
CodeCompletionString::Chunk
-CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
+CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
return Chunk(CK_Informative, Informative);
}
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateCurrentParameter(
+ StringRef CurrentParameter) {
+ return Chunk(CK_CurrentParameter, CurrentParameter);
+}
+
+
void
CodeCompletionString::Chunk::Destroy() {
switch (Kind) {
@@ -67,10 +125,23 @@ CodeCompletionString::Chunk::Destroy() {
delete Optional;
break;
+ case CK_TypedText:
case CK_Text:
case CK_Placeholder:
case CK_Informative:
- delete [] Text;
+ case CK_CurrentParameter:
+ delete [] Text;
+ break;
+
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
break;
}
}
@@ -86,16 +157,322 @@ std::string CodeCompletionString::getAsString() const {
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
switch (C->Kind) {
- case CK_Text: OS << C->Text; break;
case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
case CK_Informative: OS << "[#" << C->Text << "#]"; break;
+ case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
+ default: OS << C->Text; break;
}
}
OS.flush();
return Result;
}
+
+namespace {
+ // Escape a string for XML-like formatting.
+ struct EscapedString {
+ EscapedString(llvm::StringRef Str) : Str(Str) { }
+
+ llvm::StringRef Str;
+ };
+
+ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
+ llvm::StringRef Str = EStr.Str;
+ while (!Str.empty()) {
+ // Find the next escaped character.
+ llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
+
+ // Print everything before that escaped character.
+ OS << Str.substr(0, Pos);
+
+ // If we didn't find any escaped characters, we're done.
+ if (Pos == llvm::StringRef::npos)
+ break;
+
+ // Print the appropriate escape sequence.
+ switch (Str[Pos]) {
+ case '<': OS << "&lt;"; break;
+ case '>': OS << "&gt;"; break;
+ case '&': OS << "&amp;"; break;
+ case '"': OS << "&quot;"; break;
+ case '\'': OS << "&apos;"; break;
+ }
+
+ // Remove everything up to and including that escaped character.
+ Str = Str.substr(Pos + 1);
+ }
+
+ return OS;
+ }
+
+ /// \brief Remove XML-like escaping from a string.
+ std::string UnescapeString(llvm::StringRef Str) {
+ using llvm::StringRef;
+
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+
+ while (!Str.empty()) {
+ StringRef::size_type Amp = Str.find('&');
+ OS << Str.substr(0, Amp);
+
+ if (Amp == StringRef::npos)
+ break;
+
+ StringRef::size_type Semi = Str.substr(Amp).find(';');
+ if (Semi == StringRef::npos) {
+ // Malformed input; do the best we can.
+ OS << '&';
+ Str = Str.substr(Amp + 1);
+ continue;
+ }
+
+ char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
+ .Case("lt", '<')
+ .Case("gt", '>')
+ .Case("amp", '&')
+ .Case("quot", '"')
+ .Case("apos", '\'')
+ .Default('\0');
+
+ if (Unescaped)
+ OS << Unescaped;
+ else
+ OS << Str.substr(Amp, Semi + 1);
+ Str = Str.substr(Amp + Semi + 1);
+ }
+
+ return OS.str();
+ }
+}
+
+void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
+ switch (C->Kind) {
+ case CK_TypedText:
+ OS << "<typed-text>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_Text:
+ OS << "<text>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_Optional:
+ OS << "<optional>";
+ C->Optional->Serialize(OS);
+ OS << "</>";
+ break;
+ case CK_Placeholder:
+ OS << "<placeholder>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_Informative:
+ OS << "<informative>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_CurrentParameter:
+ OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_LeftParen:
+ OS << "<lparen/>";
+ break;
+ case CK_RightParen:
+ OS << "<rparen/>";
+ break;
+ case CK_LeftBracket:
+ OS << "<lbracket/>";
+ break;
+ case CK_RightBracket:
+ OS << "<rbracket/>";
+ break;
+ case CK_LeftBrace:
+ OS << "<lbrace/>";
+ break;
+ case CK_RightBrace:
+ OS << "<rbrace/>";
+ break;
+ case CK_LeftAngle:
+ OS << "<langle/>";
+ break;
+ case CK_RightAngle:
+ OS << "<rangle/>";
+ break;
+ case CK_Comma:
+ OS << "<comma/>";
+ break;
+ }
+ }
+}
+
+/// \brief Parse the next XML-ish tag of the form <blah>.
+///
+/// \param Str the string in which we're looking for the next tag.
+///
+/// \param TagPos if successful, will be set to the start of the tag we found.
+///
+/// \param Standalone will indicate whether this is a "standalone" tag that
+/// has no associated data, e.g., <comma/>.
+///
+/// \param Terminator will indicate whether this is a terminating tag (that is
+/// or starts with '/').
+///
+/// \returns the tag itself, without the angle brackets.
+static llvm::StringRef ParseNextTag(llvm::StringRef Str,
+ llvm::StringRef::size_type &StartTag,
+ llvm::StringRef::size_type &AfterTag,
+ bool &Standalone, bool &Terminator) {
+ using llvm::StringRef;
+
+ Standalone = false;
+ Terminator = false;
+ AfterTag = StringRef::npos;
+
+ // Find the starting '<'.
+ StartTag = Str.find('<');
+ if (StartTag == StringRef::npos)
+ return llvm::StringRef();
+
+ // Find the corresponding '>'.
+ llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
+ if (EndTag == StringRef::npos)
+ return llvm::StringRef();
+ AfterTag = StartTag + EndTag + 1;
+
+ // Determine whether this is a terminating tag.
+ if (Str[StartTag + 1] == '/') {
+ Terminator = true;
+ Str = Str.substr(1);
+ --EndTag;
+ }
+
+ // Determine whether this is a standalone tag.
+ if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
+ Standalone = true;
+ if (EndTag > 1)
+ --EndTag;
+ }
+
+ return Str.substr(StartTag + 1, EndTag - 1);
+}
+
+CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
+ using llvm::StringRef;
+
+ CodeCompletionString *Result = new CodeCompletionString;
+
+ do {
+ // Parse the next tag.
+ StringRef::size_type StartTag, AfterTag;
+ bool Standalone, Terminator;
+ StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
+ Terminator);
+
+ if (StartTag == StringRef::npos)
+ break;
+
+ // Figure out what kind of chunk we have.
+ const unsigned UnknownKind = 10000;
+ unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
+ .Case("typed-text", CK_TypedText)
+ .Case("text", CK_Text)
+ .Case("optional", CK_Optional)
+ .Case("placeholder", CK_Placeholder)
+ .Case("informative", CK_Informative)
+ .Case("current-parameter", CK_CurrentParameter)
+ .Case("lparen", CK_LeftParen)
+ .Case("rparen", CK_RightParen)
+ .Case("lbracket", CK_LeftBracket)
+ .Case("rbracket", CK_RightBracket)
+ .Case("lbrace", CK_LeftBrace)
+ .Case("rbrace", CK_RightBrace)
+ .Case("langle", CK_LeftAngle)
+ .Case("rangle", CK_RightAngle)
+ .Case("comma", CK_Comma)
+ .Default(UnknownKind);
+
+ // If we've hit a terminator tag, we're done.
+ if (Terminator)
+ break;
+
+ // Consume the tag.
+ Str = Str.substr(AfterTag);
+
+ // Handle standalone tags now, since they don't need to be matched to
+ // anything.
+ if (Standalone) {
+ // Ignore anything we don't know about.
+ if (Kind == UnknownKind)
+ continue;
+
+ switch ((ChunkKind)Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Optional:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter:
+ // There is no point in creating empty chunks of these kinds.
+ break;
+
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
+ Result->AddChunk(Chunk((ChunkKind)Kind));
+ break;
+ }
+
+ continue;
+ }
+
+ if (Kind == CK_Optional) {
+ // Deserialize the optional code-completion string.
+ std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
+ Result->AddOptionalChunk(Optional);
+ }
+
+ StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
+ Terminator);
+ if (StartTag == StringRef::npos || !Terminator || Standalone)
+ break; // Parsing failed; just give up.
+
+ if (EndTag.empty() || Tag == EndTag) {
+ // Found the matching end tag. Add this chunk based on the text
+ // between the tags, then consume that input.
+ StringRef Text = Str.substr(0, StartTag);
+ switch ((ChunkKind)Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter:
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
+ Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
+ break;
+
+ case CK_Optional:
+ // We've already added the optional chunk.
+ break;
+ }
+ }
+
+ // Remove this tag.
+ Str = Str.substr(AfterTag);
+ } while (!Str.empty());
+
+ return Result;
+}
+
//===----------------------------------------------------------------------===//
// Code completion overload candidate implementation
//===----------------------------------------------------------------------===//
@@ -133,7 +510,8 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
CodeCompleteConsumer::~CodeCompleteConsumer() { }
void
-PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
+PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+ Result *Results,
unsigned NumResults) {
// Print the results.
for (unsigned I = 0; I != NumResults; ++I) {
@@ -177,7 +555,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
}
void
-PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
+PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+ unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates) {
for (unsigned I = 0; I != NumCandidates; ++I) {
@@ -193,3 +572,87 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
// FIXME: Move this somewhere else!
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
}
+
+void
+CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+ Result *Results,
+ unsigned NumResults) {
+ // Print the results.
+ for (unsigned I = 0; I != NumResults; ++I) {
+ OS << "COMPLETION:" << Results[I].Rank << ":";
+ switch (Results[I].Kind) {
+ case Result::RK_Declaration:
+ if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
+ if (Record->isStruct())
+ OS << "Struct:";
+ else if (Record->isUnion())
+ OS << "Union:";
+ else
+ OS << "Class:";
+ } else if (ObjCMethodDecl *Method
+ = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
+ if (Method->isInstanceMethod())
+ OS << "ObjCInstanceMethod:";
+ else
+ OS << "ObjCClassMethod:";
+ } else {
+ OS << Results[I].Declaration->getDeclKindName() << ":";
+ }
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef)) {
+ CCS->Serialize(OS);
+ delete CCS;
+ } else {
+ OS << "<typed-text>"
+ << Results[I].Declaration->getNameAsString()
+ << "</>";
+ }
+
+ OS << '\n';
+ break;
+
+ case Result::RK_Keyword:
+ OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
+ break;
+
+ case Result::RK_Macro: {
+ OS << "Macro:";
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef)) {
+ CCS->Serialize(OS);
+ delete CCS;
+ } else {
+ OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
+ }
+ OS << '\n';
+ break;
+ }
+ }
+ }
+
+ // Once we've printed the code-completion results, suppress remaining
+ // diagnostics.
+ // FIXME: Move this somewhere else!
+ SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
+
+void
+CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+ unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) {
+ for (unsigned I = 0; I != NumCandidates; ++I) {
+ if (CodeCompletionString *CCS
+ = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
+ OS << "OVERLOAD:";
+ CCS->Serialize(OS);
+ OS << '\n';
+ delete CCS;
+ }
+ }
+
+ // Once we've printed the code-completion results, suppress remaining
+ // diagnostics.
+ // FIXME: Move this somewhere else!
+ SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index a8e31d2cfa2b..2b37e9df2c0e 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -325,5 +325,5 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To,
}
void Sema::DiagnoseInvalidJumps(Stmt *Body) {
- JumpScopeChecker(Body, *this);
+ (void)JumpScopeChecker(Body, *this);
}
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
new file mode 100644
index 000000000000..6e72dcef161a
--- /dev/null
+++ b/lib/Sema/Lookup.h
@@ -0,0 +1,392 @@
+//===--- Lookup.h - Classes for name lookup ---------------------*- 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 LookupResult class, which is integral to
+// Sema's name-lookup subsystem.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_LOOKUP_H
+#define LLVM_CLANG_SEMA_LOOKUP_H
+
+#include "Sema.h"
+
+namespace clang {
+
+/// @brief Represents the results of name lookup.
+///
+/// An instance of the LookupResult class captures the results of a
+/// single name lookup, which can return no result (nothing found),
+/// a single declaration, a set of overloaded functions, or an
+/// ambiguity. Use the getKind() method to determine which of these
+/// results occurred for a given lookup.
+///
+/// Any non-ambiguous lookup can be converted into a single
+/// (possibly NULL) @c NamedDecl* via the getAsSingleDecl() method.
+/// This permits the common-case usage in C and Objective-C where
+/// name lookup will always return a single declaration. Use of
+/// this is largely deprecated; callers should handle the possibility
+/// of multiple declarations.
+class LookupResult {
+public:
+ enum LookupResultKind {
+ /// @brief No entity found met the criteria.
+ NotFound = 0,
+
+ /// @brief Name lookup found a single declaration that met the
+ /// criteria. getAsDecl will return this declaration.
+ Found,
+
+ /// @brief Name lookup found a set of overloaded functions that
+ /// met the criteria. getAsDecl will turn this set of overloaded
+ /// functions into an OverloadedFunctionDecl.
+ FoundOverloaded,
+
+ /// @brief Name lookup found an unresolvable value declaration
+ /// and cannot yet complete. This only happens in C++ dependent
+ /// contexts with dependent using declarations.
+ FoundUnresolvedValue,
+
+ /// @brief Name lookup results in an ambiguity; use
+ /// getAmbiguityKind to figure out what kind of ambiguity
+ /// we have.
+ Ambiguous
+ };
+
+ enum AmbiguityKind {
+ /// Name lookup results in an ambiguity because multiple
+ /// entities that meet the lookup criteria were found in
+ /// subobjects of different types. For example:
+ /// @code
+ /// struct A { void f(int); }
+ /// struct B { void f(double); }
+ /// struct C : A, B { };
+ /// void test(C c) {
+ /// c.f(0); // error: A::f and B::f come from subobjects of different
+ /// // types. overload resolution is not performed.
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjectTypes,
+
+ /// Name lookup results in an ambiguity because multiple
+ /// nonstatic entities that meet the lookup criteria were found
+ /// in different subobjects of the same type. For example:
+ /// @code
+ /// struct A { int x; };
+ /// struct B : A { };
+ /// struct C : A { };
+ /// struct D : B, C { };
+ /// int test(D d) {
+ /// return d.x; // error: 'x' is found in two A subobjects (of B and C)
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjects,
+
+ /// Name lookup results in an ambiguity because multiple definitions
+ /// of entity that meet the lookup criteria were found in different
+ /// declaration contexts.
+ /// @code
+ /// namespace A {
+ /// int i;
+ /// namespace B { int i; }
+ /// int test() {
+ /// using namespace B;
+ /// return i; // error 'i' is found in namespace A and A::B
+ /// }
+ /// }
+ /// @endcode
+ AmbiguousReference,
+
+ /// Name lookup results in an ambiguity because an entity with a
+ /// tag name was hidden by an entity with an ordinary name from
+ /// a different context.
+ /// @code
+ /// namespace A { struct Foo {}; }
+ /// namespace B { void Foo(); }
+ /// namespace C {
+ /// using namespace A;
+ /// using namespace B;
+ /// }
+ /// void test() {
+ /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
+ /// // different namespace
+ /// }
+ /// @endcode
+ AmbiguousTagHiding
+ };
+
+ /// A little identifier for flagging temporary lookup results.
+ enum TemporaryToken {
+ Temporary
+ };
+
+ typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
+ typedef DeclsTy::const_iterator iterator;
+
+ LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
+ Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : ResultKind(NotFound),
+ Paths(0),
+ SemaRef(SemaRef),
+ Name(Name),
+ NameLoc(NameLoc),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration)
+ {}
+
+ /// Creates a temporary lookup result, initializing its core data
+ /// using the information from another result. Diagnostics are always
+ /// disabled.
+ LookupResult(TemporaryToken _, const LookupResult &Other)
+ : ResultKind(NotFound),
+ Paths(0),
+ SemaRef(Other.SemaRef),
+ Name(Other.Name),
+ NameLoc(Other.NameLoc),
+ LookupKind(Other.LookupKind),
+ IDNS(Other.IDNS),
+ Redecl(Other.Redecl),
+ HideTags(Other.HideTags),
+ Diagnose(false)
+ {}
+
+ ~LookupResult() {
+ if (Diagnose) diagnose();
+ if (Paths) deletePaths(Paths);
+ }
+
+ /// Gets the name to look up.
+ DeclarationName getLookupName() const {
+ return Name;
+ }
+
+ /// Gets the kind of lookup to perform.
+ Sema::LookupNameKind getLookupKind() const {
+ return LookupKind;
+ }
+
+ /// True if this lookup is just looking for an existing declaration.
+ bool isForRedeclaration() const {
+ return Redecl;
+ }
+
+ /// Sets whether tag declarations should be hidden by non-tag
+ /// declarations during resolution. The default is true.
+ void setHideTags(bool Hide) {
+ HideTags = Hide;
+ }
+
+ /// The identifier namespace of this lookup. This information is
+ /// private to the lookup routines.
+ unsigned getIdentifierNamespace() const {
+ assert(IDNS);
+ return IDNS;
+ }
+
+ void setIdentifierNamespace(unsigned NS) {
+ IDNS = NS;
+ }
+
+ bool isAmbiguous() const {
+ return getResultKind() == Ambiguous;
+ }
+
+ LookupResultKind getResultKind() const {
+ sanity();
+ return ResultKind;
+ }
+
+ AmbiguityKind getAmbiguityKind() const {
+ assert(isAmbiguous());
+ return Ambiguity;
+ }
+
+ iterator begin() const { return Decls.begin(); }
+ iterator end() const { return Decls.end(); }
+
+ /// \brief Return true if no decls were found
+ bool empty() const { return Decls.empty(); }
+
+ /// \brief Return the base paths structure that's associated with
+ /// these results, or null if none is.
+ CXXBasePaths *getBasePaths() const {
+ return Paths;
+ }
+
+ /// \brief Add a declaration to these results.
+ void addDecl(NamedDecl *D) {
+ Decls.push_back(D);
+ ResultKind = Found;
+ }
+
+ /// \brief Add all the declarations from another set of lookup
+ /// results.
+ void addAllDecls(const LookupResult &Other) {
+ Decls.append(Other.begin(), Other.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 Resolves the kind of the lookup, possibly hiding decls.
+ ///
+ /// This should be called in any environment where lookup might
+ /// generate multiple lookup results.
+ void resolveKind();
+
+ /// \brief Fetch this as an unambiguous single declaration
+ /// (possibly an overloaded one).
+ ///
+ /// This is deprecated; users should be written to handle
+ /// ambiguous and overloaded lookups.
+ NamedDecl *getAsSingleDecl(ASTContext &Context) const;
+
+ /// \brief Fetch the unique decl found by this lookup. Asserts
+ /// that one was found.
+ ///
+ /// This is intended for users who have examined the result kind
+ /// and are certain that there is only one result.
+ NamedDecl *getFoundDecl() const {
+ assert(getResultKind() == Found
+ && "getFoundDecl called on non-unique result");
+ return Decls[0]->getUnderlyingDecl();
+ }
+
+ /// \brief Asks if the result is a single tag decl.
+ bool isSingleTagDecl() const {
+ return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
+ }
+
+ /// \brief Make these results show that the name was found in
+ /// base classes of different types.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
+
+ /// \brief Make these results show that the name was found in
+ /// distinct base classes of the same type.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjects(CXXBasePaths &P);
+
+ /// \brief Make these results show that the name was found in
+ /// different contexts and a tag decl was hidden by an ordinary
+ /// decl in a different context.
+ void setAmbiguousQualifiedTagHiding() {
+ setAmbiguous(AmbiguousTagHiding);
+ }
+
+ /// \brief Clears out any current state.
+ void clear() {
+ ResultKind = NotFound;
+ Decls.clear();
+ if (Paths) deletePaths(Paths);
+ Paths = NULL;
+ }
+
+ /// \brief Clears out any current state and re-initializes for a
+ /// different kind of lookup.
+ void clear(Sema::LookupNameKind Kind) {
+ clear();
+ LookupKind = Kind;
+ }
+
+ void print(llvm::raw_ostream &);
+
+ /// Suppress the diagnostics that would normally fire because of this
+ /// lookup. This happens during (e.g.) redeclaration lookups.
+ void suppressDiagnostics() {
+ Diagnose = false;
+ }
+
+ /// Sets a 'context' source range.
+ void setContextRange(SourceRange SR) {
+ NameContextRange = SR;
+ }
+
+ /// Gets the source range of the context of this name; for C++
+ /// qualified lookups, this is the source range of the scope
+ /// specifier.
+ SourceRange getContextRange() const {
+ return NameContextRange;
+ }
+
+ /// Gets the location of the identifier. This isn't always defined:
+ /// sometimes we're doing lookups on synthesized names.
+ SourceLocation getNameLoc() const {
+ return NameLoc;
+ }
+
+private:
+ void diagnose() {
+ if (isAmbiguous())
+ SemaRef.DiagnoseAmbiguousLookup(*this);
+ }
+
+ void setAmbiguous(AmbiguityKind AK) {
+ ResultKind = Ambiguous;
+ Ambiguity = AK;
+ }
+
+ void addDeclsFromBasePaths(const CXXBasePaths &P);
+
+ // Sanity checks.
+ void sanity() const {
+ assert(ResultKind != NotFound || Decls.size() == 0);
+ assert(ResultKind != Found || Decls.size() == 1);
+ assert(ResultKind == NotFound || ResultKind == Found ||
+ ResultKind == FoundUnresolvedValue ||
+ (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
+ || Decls.size() > 1);
+ assert((Paths != NULL) == (ResultKind == Ambiguous &&
+ (Ambiguity == AmbiguousBaseSubobjectTypes ||
+ Ambiguity == AmbiguousBaseSubobjects)));
+ }
+
+ static void deletePaths(CXXBasePaths *);
+
+ // Results.
+ LookupResultKind ResultKind;
+ AmbiguityKind Ambiguity; // ill-defined unless ambiguous
+ DeclsTy Decls;
+ CXXBasePaths *Paths;
+
+ // Parameters.
+ Sema &SemaRef;
+ DeclarationName Name;
+ SourceLocation NameLoc;
+ SourceRange NameContextRange;
+ Sema::LookupNameKind LookupKind;
+ unsigned IDNS; // ill-defined until set by lookup
+ bool Redecl;
+
+ /// \brief True if tag declarations should be hidden if non-tags
+ /// are present
+ bool HideTags;
+
+ bool Diagnose;
+};
+
+}
+
+#endif
diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp
index d3f26d875cc4..7b223a8fa3b6 100644
--- a/lib/Sema/ParseAST.cpp
+++ b/lib/Sema/ParseAST.cpp
@@ -35,15 +35,14 @@ using namespace clang;
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
ASTContext &Ctx, bool PrintStats,
bool CompleteTranslationUnit,
- CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data),
- void *CreateCodeCompleterData) {
+ CodeCompleteConsumer *CompletionConsumer) {
// Collect global stats on Decls/Stmts (until we have a module streamer).
if (PrintStats) {
Decl::CollectingStats(true);
Stmt::CollectingStats(true);
}
- Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit);
+ Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer);
Parser P(PP, S);
PP.EnterMainSourceFile();
@@ -63,12 +62,6 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
External->StartTranslationUnit(Consumer);
}
- CodeCompleteConsumer *CodeCompleter = 0;
- if (CreateCodeCompleter) {
- CodeCompleter = CreateCodeCompleter(S, CreateCodeCompleterData);
- S.setCodeCompleteConsumer(CodeCompleter);
- }
-
Parser::DeclGroupPtrTy ADecl;
while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file.
@@ -78,6 +71,9 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
if (ADecl)
Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
};
+ // Check for any pending objective-c implementation decl.
+ while ((ADecl = P.RetrievePendingObjCImpDecl()))
+ Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
// process any TopLevelDecls generated by #pragma weak
for (llvm::SmallVector<Decl*,2>::iterator
@@ -87,9 +83,6 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
Consumer->HandleTranslationUnit(Ctx);
- if (CreateCodeCompleter)
- delete CodeCompleter;
-
if (PrintStats) {
fprintf(stderr, "\nSTATISTICS:\n");
P.getActions().PrintStats();
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 8104dd39d052..b2bbac8bc2a9 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -14,6 +14,7 @@
#include "Sema.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/APFloat.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -346,16 +347,18 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
- bool CompleteTranslationUnit)
+ bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CodeCompleter)
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
- ExternalSource(0), CodeCompleter(0), CurContext(0),
+ ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
CompleteTranslationUnit(CompleteTranslationUnit),
- NumSFINAEErrors(0), CurrentInstantiationScope(0) {
-
+ NumSFINAEErrors(0), NonInstantiationEntries(0),
+ CurrentInstantiationScope(0)
+{
TUScope = 0;
if (getLangOptions().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
@@ -364,6 +367,322 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context);
}
+/// Retrieves the width and signedness of the given integer type,
+/// or returns false if it is not an integer type.
+///
+/// \param T must be canonical
+static bool getIntProperties(ASTContext &C, const Type *T,
+ unsigned &BitWidth, bool &Signed) {
+ assert(T->isCanonicalUnqualified());
+
+ if (const VectorType *VT = dyn_cast<VectorType>(T))
+ T = VT->getElementType().getTypePtr();
+ if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+ T = CT->getElementType().getTypePtr();
+
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
+ if (!BT->isInteger()) return false;
+
+ BitWidth = C.getIntWidth(QualType(T, 0));
+ Signed = BT->isSignedInteger();
+ return true;
+ }
+
+ if (const FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
+ BitWidth = FWIT->getWidth();
+ Signed = FWIT->isSigned();
+ return true;
+ }
+
+ return false;
+}
+
+/// Checks whether the given value will have the same value if it it
+/// is truncated to the given width, then extended back to the
+/// original width.
+static bool IsSameIntAfterCast(const llvm::APSInt &value,
+ unsigned TargetWidth) {
+ unsigned SourceWidth = value.getBitWidth();
+ llvm::APSInt truncated = value;
+ truncated.trunc(TargetWidth);
+ truncated.extend(SourceWidth);
+ return (truncated == value);
+}
+
+/// Checks whether the given value will have the same value if it
+/// is truncated to the given width, then extended back to the original
+/// width.
+///
+/// The value might be a vector or a complex.
+static bool IsSameIntAfterCast(const APValue &value, unsigned TargetWidth) {
+ if (value.isInt())
+ return IsSameIntAfterCast(value.getInt(), TargetWidth);
+
+ if (value.isVector()) {
+ for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
+ if (!IsSameIntAfterCast(value.getVectorElt(i), TargetWidth))
+ return false;
+ return true;
+ }
+
+ if (value.isComplexInt()) {
+ return IsSameIntAfterCast(value.getComplexIntReal(), TargetWidth) &&
+ IsSameIntAfterCast(value.getComplexIntImag(), TargetWidth);
+ }
+
+ // This can happen with lossless casts to intptr_t of "based" lvalues.
+ // Assume it might use arbitrary bits.
+ assert(value.isLValue());
+ return false;
+}
+
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+static bool IsSameFloatAfterCast(const llvm::APFloat &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
+ llvm::APFloat truncated = value;
+
+ bool ignored;
+ truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
+ truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
+
+ return truncated.bitwiseIsEqual(value);
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+///
+/// The value might be a vector of floats (or a complex number).
+static bool IsSameFloatAfterCast(const APValue &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
+ if (value.isFloat())
+ return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
+
+ if (value.isVector()) {
+ for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
+ if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
+ return false;
+ return true;
+ }
+
+ assert(value.isComplexFloat());
+ return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
+ IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
+}
+
+/// Determines if it's reasonable for the given expression to be truncated
+/// down to the given integer width.
+/// * Boolean expressions are automatically white-listed.
+/// * Arithmetic operations on implicitly-promoted operands of the
+/// target width or less are okay --- not because the results are
+/// actually guaranteed to fit within the width, but because the
+/// user is effectively pretending that the operations are closed
+/// within the implicitly-promoted type.
+static bool IsExprValueWithinWidth(ASTContext &C, Expr *E, unsigned Width) {
+ E = E->IgnoreParens();
+
+#ifndef NDEBUG
+ {
+ const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
+ unsigned EWidth;
+ bool ESigned;
+
+ if (!getIntProperties(C, ETy, EWidth, ESigned))
+ assert(0 && "expression not of integer type");
+
+ // The caller should never let this happen.
+ assert(EWidth > Width && "called on expr whose type is too small");
+ }
+#endif
+
+ // Strip implicit casts off.
+ while (isa<ImplicitCastExpr>(E)) {
+ E = cast<ImplicitCastExpr>(E)->getSubExpr();
+
+ const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
+
+ unsigned EWidth;
+ bool ESigned;
+ if (!getIntProperties(C, ETy, EWidth, ESigned))
+ return false;
+
+ if (EWidth <= Width)
+ return true;
+ }
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ switch (BO->getOpcode()) {
+
+ // Boolean-valued operations are white-listed.
+ case BinaryOperator::LAnd:
+ case BinaryOperator::LOr:
+ case BinaryOperator::LT:
+ case BinaryOperator::GT:
+ case BinaryOperator::LE:
+ case BinaryOperator::GE:
+ case BinaryOperator::EQ:
+ case BinaryOperator::NE:
+ return true;
+
+ // Operations with opaque sources are black-listed.
+ case BinaryOperator::PtrMemD:
+ case BinaryOperator::PtrMemI:
+ return false;
+
+ // Left shift gets black-listed based on a judgement call.
+ case BinaryOperator::Shl:
+ return false;
+
+ // Various special cases.
+ case BinaryOperator::Shr:
+ return IsExprValueWithinWidth(C, BO->getLHS(), Width);
+ case BinaryOperator::Comma:
+ return IsExprValueWithinWidth(C, BO->getRHS(), Width);
+ case BinaryOperator::Sub:
+ if (BO->getLHS()->getType()->isPointerType())
+ return false;
+ // fallthrough
+
+ // Any other operator is okay if the operands are
+ // promoted from expressions of appropriate size.
+ default:
+ return IsExprValueWithinWidth(C, BO->getLHS(), Width) &&
+ IsExprValueWithinWidth(C, BO->getRHS(), Width);
+ }
+ }
+
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ switch (UO->getOpcode()) {
+ // Boolean-valued operations are white-listed.
+ case UnaryOperator::LNot:
+ return true;
+
+ // Operations with opaque sources are black-listed.
+ case UnaryOperator::Deref:
+ case UnaryOperator::AddrOf: // should be impossible
+ return false;
+
+ case UnaryOperator::OffsetOf:
+ return false;
+
+ default:
+ return IsExprValueWithinWidth(C, UO->getSubExpr(), Width);
+ }
+ }
+
+ // Don't diagnose if the expression is an integer constant
+ // whose value in the target type is the same as it was
+ // in the original type.
+ Expr::EvalResult result;
+ if (E->Evaluate(result, C))
+ if (IsSameIntAfterCast(result.Val, Width))
+ return true;
+
+ return false;
+}
+
+/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
+ S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange();
+}
+
+/// Implements -Wconversion.
+static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) {
+ // Don't diagnose in unevaluated contexts.
+ if (S.ExprEvalContext == Sema::Unevaluated)
+ return;
+
+ // Don't diagnose for value-dependent expressions.
+ if (E->isValueDependent())
+ return;
+
+ const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
+ const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
+
+ // Never diagnose implicit casts to bool.
+ if (Target->isSpecificBuiltinType(BuiltinType::Bool))
+ return;
+
+ // Strip vector types.
+ if (isa<VectorType>(Source)) {
+ if (!isa<VectorType>(Target))
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_vector_scalar);
+
+ Source = cast<VectorType>(Source)->getElementType().getTypePtr();
+ Target = cast<VectorType>(Target)->getElementType().getTypePtr();
+ }
+
+ // Strip complex types.
+ if (isa<ComplexType>(Source)) {
+ if (!isa<ComplexType>(Target))
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_complex_scalar);
+
+ Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
+ Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
+ }
+
+ const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
+ const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);
+
+ // If the source is floating point...
+ if (SourceBT && SourceBT->isFloatingPoint()) {
+ // ...and the target is floating point...
+ if (TargetBT && TargetBT->isFloatingPoint()) {
+ // ...then warn if we're dropping FP rank.
+
+ // Builtin FP kinds are ordered by increasing FP rank.
+ if (SourceBT->getKind() > TargetBT->getKind()) {
+ // Don't warn about float constants that are precisely
+ // representable in the target type.
+ Expr::EvalResult result;
+ if (E->Evaluate(result, S.Context)) {
+ // Value might be a float, a float vector, or a float complex.
+ if (IsSameFloatAfterCast(result.Val,
+ S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
+ S.Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
+ return;
+ }
+
+ DiagnoseImpCast(S, E, T, diag::warn_impcast_float_precision);
+ }
+ return;
+ }
+
+ // If the target is integral, always warn.
+ if ((TargetBT && TargetBT->isInteger()) ||
+ isa<FixedWidthIntType>(Target))
+ // TODO: don't warn for integer values?
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer);
+
+ return;
+ }
+
+ unsigned SourceWidth, TargetWidth;
+ bool SourceSigned, TargetSigned;
+
+ if (!getIntProperties(S.Context, Source, SourceWidth, SourceSigned) ||
+ !getIntProperties(S.Context, Target, TargetWidth, TargetSigned))
+ return;
+
+ if (SourceWidth > TargetWidth) {
+ if (IsExprValueWithinWidth(S.Context, E, TargetWidth))
+ return;
+
+ // People want to build with -Wshorten-64-to-32 and not -Wconversion
+ // and by god we'll let them.
+ if (SourceWidth == 64 && TargetWidth == 32)
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_64_32);
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_precision);
+ }
+
+ return;
+}
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
@@ -375,18 +694,17 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
if (ExprTy == TypeTy)
return;
- if (Expr->getType().getTypePtr()->isPointerType() &&
- Ty.getTypePtr()->isPointerType()) {
- QualType ExprBaseType =
- cast<PointerType>(ExprTy.getUnqualifiedType())->getPointeeType();
- QualType BaseType =
- cast<PointerType>(TypeTy.getUnqualifiedType())->getPointeeType();
+ if (Expr->getType()->isPointerType() && Ty->isPointerType()) {
+ QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType();
+ QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType();
if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) {
Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast)
<< Expr->getSourceRange();
}
}
+ CheckImplicitConversion(*this, Expr, Ty);
+
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
if (ImpCast->getCastKind() == Kind) {
ImpCast->setType(Ty);
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index c4de6be9eb2e..3e186b2b5be9 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -93,6 +93,7 @@ namespace clang {
class FunctionProtoType;
class CXXBasePaths;
class CXXTemporary;
+ class LookupResult;
/// BlockSemaInfo - When a block is being parsed, this contains information
/// about the block. It is pointed to from Sema::CurBlock.
@@ -373,7 +374,8 @@ public:
bool isSelfExpr(Expr *RExpr);
public:
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
- bool CompleteTranslationUnit = true);
+ bool CompleteTranslationUnit = true,
+ CodeCompleteConsumer *CompletionConsumer = 0);
~Sema() {
if (PackContext) FreePackedContext();
}
@@ -804,13 +806,15 @@ public:
QualType& ConvertedType, bool &IncompatibleObjC);
bool isObjCPointerConversion(QualType FromType, QualType ToType,
QualType& ConvertedType, bool &IncompatibleObjC);
- bool CheckPointerConversion(Expr *From, QualType ToType,
- CastExpr::CastKind &Kind);
+ bool CheckPointerConversion(Expr *From, QualType ToType,
+ CastExpr::CastKind &Kind,
+ bool IgnoreBaseAccess);
bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
bool InOverloadResolution,
QualType &ConvertedType);
bool CheckMemberPointerConversion(Expr *From, QualType ToType,
- CastExpr::CastKind &Kind);
+ CastExpr::CastKind &Kind,
+ bool IgnoreBaseAccess);
bool IsQualificationConversion(QualType FromType, QualType ToType);
OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
@@ -870,6 +874,11 @@ public:
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
+ void AddMethodCandidate(NamedDecl *Decl,
+ Expr *Object, Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversion = false,
+ bool ForceRValue = false);
void AddMethodCandidate(CXXMethodDecl *Method,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -1073,255 +1082,14 @@ public:
LookupObjCCategoryImplName
};
- /// @brief Represents the results of name lookup.
- ///
- /// An instance of the LookupResult class captures the results of a
- /// single name lookup, which can return no result (nothing found),
- /// a single declaration, a set of overloaded functions, or an
- /// ambiguity. Use the getKind() method to determine which of these
- /// results occurred for a given lookup.
- ///
- /// Any non-ambiguous lookup can be converted into a single
- /// (possibly NULL) @c NamedDecl* via the getAsSingleDecl() method.
- /// This permits the common-case usage in C and Objective-C where
- /// name lookup will always return a single declaration. Use of
- /// this is largely deprecated; callers should handle the possibility
- /// of multiple declarations.
- class LookupResult {
- public:
- enum LookupKind {
- /// @brief No entity found met the criteria.
- NotFound = 0,
-
- /// @brief Name lookup found a single declaration that met the
- /// criteria. getAsDecl will return this declaration.
- Found,
-
- /// @brief Name lookup found a set of overloaded functions that
- /// met the criteria. getAsDecl will turn this set of overloaded
- /// functions into an OverloadedFunctionDecl.
- FoundOverloaded,
-
- /// @brief Name lookup results in an ambiguity; use
- /// getAmbiguityKind to figure out what kind of ambiguity
- /// we have.
- Ambiguous
- };
-
- enum AmbiguityKind {
- /// Name lookup results in an ambiguity because multiple
- /// entities that meet the lookup criteria were found in
- /// subobjects of different types. For example:
- /// @code
- /// struct A { void f(int); }
- /// struct B { void f(double); }
- /// struct C : A, B { };
- /// void test(C c) {
- /// c.f(0); // error: A::f and B::f come from subobjects of different
- /// // types. overload resolution is not performed.
- /// }
- /// @endcode
- AmbiguousBaseSubobjectTypes,
-
- /// Name lookup results in an ambiguity because multiple
- /// nonstatic entities that meet the lookup criteria were found
- /// in different subobjects of the same type. For example:
- /// @code
- /// struct A { int x; };
- /// struct B : A { };
- /// struct C : A { };
- /// struct D : B, C { };
- /// int test(D d) {
- /// return d.x; // error: 'x' is found in two A subobjects (of B and C)
- /// }
- /// @endcode
- AmbiguousBaseSubobjects,
-
- /// Name lookup results in an ambiguity because multiple definitions
- /// of entity that meet the lookup criteria were found in different
- /// declaration contexts.
- /// @code
- /// namespace A {
- /// int i;
- /// namespace B { int i; }
- /// int test() {
- /// using namespace B;
- /// return i; // error 'i' is found in namespace A and A::B
- /// }
- /// }
- /// @endcode
- AmbiguousReference,
-
- /// Name lookup results in an ambiguity because an entity with a
- /// tag name was hidden by an entity with an ordinary name from
- /// a different context.
- /// @code
- /// namespace A { struct Foo {}; }
- /// namespace B { void Foo(); }
- /// namespace C {
- /// using namespace A;
- /// using namespace B;
- /// }
- /// void test() {
- /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
- /// // different namespace
- /// }
- /// @endcode
- AmbiguousTagHiding
- };
-
- typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
- typedef DeclsTy::const_iterator iterator;
-
- LookupResult()
- : Kind(NotFound),
- Paths(0)
- {}
- ~LookupResult() {
- if (Paths) deletePaths(Paths);
- }
-
- bool isAmbiguous() const {
- return getKind() == Ambiguous;
- }
-
- LookupKind getKind() const {
- sanity();
- return Kind;
- }
-
- AmbiguityKind getAmbiguityKind() const {
- assert(isAmbiguous());
- return Ambiguity;
- }
-
- iterator begin() const { return Decls.begin(); }
- iterator end() const { return Decls.end(); }
-
- /// \brief Return true if no decls were found
- bool empty() const { return Decls.empty(); }
-
- /// \brief Return the base paths structure that's associated with
- /// these results, or null if none is.
- CXXBasePaths *getBasePaths() const {
- return Paths;
- }
-
- /// \brief Add a declaration to these results.
- void addDecl(NamedDecl *D) {
- Decls.push_back(D->getUnderlyingDecl());
- Kind = Found;
- }
-
- /// \brief Add all the declarations from another set of lookup
- /// results.
- void addAllDecls(const LookupResult &Other) {
- Decls.append(Other.begin(), Other.end());
- Kind = 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 Resolves the kind of the lookup, possibly hiding decls.
- ///
- /// This should be called in any environment where lookup might
- /// generate multiple lookup results.
- void resolveKind();
-
- /// \brief Fetch this as an unambiguous single declaration
- /// (possibly an overloaded one).
- ///
- /// This is deprecated; users should be written to handle
- /// ambiguous and overloaded lookups.
- NamedDecl *getAsSingleDecl(ASTContext &Context) const;
-
- /// \brief Fetch the unique decl found by this lookup. Asserts
- /// that one was found.
- ///
- /// This is intended for users who have examined the result kind
- /// and are certain that there is only one result.
- NamedDecl *getFoundDecl() const {
- assert(getKind() == Found && "getFoundDecl called on non-unique result");
- return *Decls.begin();
- }
-
- /// \brief Asks if the result is a single tag decl.
- bool isSingleTagDecl() const {
- return getKind() == Found && isa<TagDecl>(getFoundDecl());
- }
-
- /// \brief Make these results show that the name was found in
- /// base classes of different types.
- ///
- /// The given paths object is copied and invalidated.
- void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
-
- /// \brief Make these results show that the name was found in
- /// distinct base classes of the same type.
- ///
- /// The given paths object is copied and invalidated.
- void setAmbiguousBaseSubobjects(CXXBasePaths &P);
-
- /// \brief Make these results show that the name was found in
- /// different contexts and a tag decl was hidden by an ordinary
- /// decl in a different context.
- void setAmbiguousQualifiedTagHiding() {
- setAmbiguous(AmbiguousTagHiding);
- }
-
- /// \brief Clears out any current state.
- void clear() {
- Kind = NotFound;
- Decls.clear();
- if (Paths) deletePaths(Paths);
- Paths = NULL;
- }
-
- void print(llvm::raw_ostream &);
-
- private:
- void setAmbiguous(AmbiguityKind AK) {
- Kind = Ambiguous;
- Ambiguity = AK;
- }
-
- void addDeclsFromBasePaths(const CXXBasePaths &P);
-
- // Sanity checks.
- void sanity() const {
- assert(Kind != NotFound || Decls.size() == 0);
- assert(Kind != Found || Decls.size() == 1);
- assert(Kind == NotFound || Kind == Found ||
- (Kind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
- || Decls.size() > 1);
- assert((Paths != NULL) == (Kind == Ambiguous &&
- (Ambiguity == AmbiguousBaseSubobjectTypes ||
- Ambiguity == AmbiguousBaseSubobjects)));
- }
-
- static void deletePaths(CXXBasePaths *);
-
- LookupKind Kind;
- AmbiguityKind Ambiguity; // ill-defined unless ambiguous
- DeclsTy Decls;
- CXXBasePaths *Paths;
+ enum RedeclarationKind {
+ NotForRedeclaration,
+ ForRedeclaration
};
private:
- typedef llvm::SmallVector<LookupResult, 3> LookupResultsVecTy;
+ bool CppLookupName(LookupResult &R, Scope *S);
- bool CppLookupName(LookupResult &R, Scope *S, DeclarationName Name,
- LookupNameKind NameKind, bool RedeclarationOnly);
public:
/// Determines whether D is a suitable lookup result according to the
/// lookup criteria.
@@ -1360,27 +1128,13 @@ public:
/// ambiguity and overloaded.
NamedDecl *LookupSingleName(Scope *S, DeclarationName Name,
LookupNameKind NameKind,
- bool RedeclarationOnly = false) {
- LookupResult R;
- LookupName(R, S, Name, NameKind, RedeclarationOnly);
- return R.getAsSingleDecl(Context);
- }
+ RedeclarationKind Redecl
+ = NotForRedeclaration);
bool LookupName(LookupResult &R, Scope *S,
- DeclarationName Name,
- LookupNameKind NameKind,
- bool RedeclarationOnly = false,
- bool AllowBuiltinCreation = false,
- SourceLocation Loc = SourceLocation());
- bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
- DeclarationName Name,
- LookupNameKind NameKind,
- bool RedeclarationOnly = false);
+ bool AllowBuiltinCreation = false);
+ bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx);
bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
- DeclarationName Name,
- LookupNameKind NameKind,
- bool RedeclarationOnly = false,
bool AllowBuiltinCreation = false,
- SourceLocation Loc = SourceLocation(),
bool EnteringContext = false);
ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II);
@@ -1398,9 +1152,7 @@ public:
AssociatedNamespaceSet &AssociatedNamespaces,
AssociatedClassSet &AssociatedClasses);
- bool DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
- SourceLocation NameLoc,
- SourceRange LookupRange = SourceRange());
+ bool DiagnoseAmbiguousLookup(LookupResult &Result);
//@}
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
@@ -1447,6 +1199,12 @@ public:
void ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
ObjCContainerDecl* IDecl,
bool IncompleteImpl = false);
+
+ /// AtomicPropertySetterGetterRules - This routine enforces the rule (via
+ /// warning) when atomic property has one but not the other user-declared
+ /// setter or getter.
+ void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl);
/// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
/// true, or false, accordingly.
@@ -1610,7 +1368,8 @@ public:
Expr **Args, unsigned NumArgs);
void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc,
- const PartialDiagnostic &PD);
+ const PartialDiagnostic &PD,
+ bool Equality = false);
virtual ExpressionEvaluationContext
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
@@ -1746,11 +1505,6 @@ public:
const FunctionProtoType *Proto,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc);
- void BuildBaseOrMemberInitializers(ASTContext &C,
- CXXConstructorDecl *Constructor,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers
- );
void DeconstructCallFunction(Expr *FnExpr,
NamedDecl *&Function,
@@ -1890,12 +1644,15 @@ public:
SourceLocation IdentLoc,
IdentifierInfo *Ident);
- NamedDecl *BuildUsingDeclaration(SourceLocation UsingLoc,
+ NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
DeclarationName Name,
AttributeList *AttrList,
- bool IsTypeName);
+ bool IsInstantiation,
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
@@ -1903,7 +1660,8 @@ public:
const CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName);
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
@@ -1997,6 +1755,12 @@ public:
};
CXXConstructorDecl *
+ TryInitializationByConstructor(QualType ClassType,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation Loc,
+ InitializationKind Kind);
+
+ CXXConstructorDecl *
PerformInitializationByConstructor(QualType ClassType,
MultiExprArg ArgsPtr,
SourceLocation Loc, SourceRange Range,
@@ -2088,6 +1852,9 @@ public:
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
QualType Argument);
+ bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+ DeclarationName Name, FunctionDecl* &Operator);
+
/// ActOnCXXDelete - Parsed a C++ 'delete' expression
virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
bool UseGlobal, bool ArrayForm,
@@ -2276,17 +2043,15 @@ public:
SourceLocation RParenLoc,
CXXRecordDecl *ClassDecl);
- void SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+ bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
- llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
- llvm::SmallVectorImpl<FieldDecl *>&Members);
+ bool IsImplicitConstructor);
- /// computeBaseOrMembersToDestroy - Compute information in current
- /// destructor decl's AST of bases and non-static data members which will be
- /// implicitly destroyed. We are storing the destruction in the order that
- /// they should occur (which is the reverse of construction order).
- void computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor);
+ /// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl,
+ /// mark all its non-trivial member and base destructor declarations
+ /// as referenced.
+ void MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor);
void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
@@ -2320,6 +2085,7 @@ public:
void CheckConstructor(CXXConstructorDecl *Constructor);
QualType CheckDestructorDeclarator(Declarator &D,
FunctionDecl::StorageClass& SC);
+ void CheckDestructor(CXXDestructorDecl *Destructor);
void CheckConversionDeclarator(Declarator &D, QualType &R,
FunctionDecl::StorageClass& SC);
DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
@@ -2353,7 +2119,8 @@ public:
bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
- SourceLocation Loc, SourceRange Range);
+ SourceLocation Loc, SourceRange Range,
+ bool IgnoreAccess = false);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
unsigned InaccessibleBaseID,
unsigned AmbigiousBaseConvID,
@@ -2451,7 +2218,7 @@ public:
unsigned Position);
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
SourceLocation EqualLoc,
- ExprArg Default);
+ const ParsedTemplateArgument &Default);
virtual TemplateParamsTy *
ActOnTemplateParameterList(unsigned Depth,
@@ -2477,8 +2244,7 @@ public:
AccessSpecifier AS);
void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
- SourceLocation *TemplateArgLocsIn,
- llvm::SmallVector<TemplateArgumentLoc, 16> &TempArgs);
+ llvm::SmallVectorImpl<TemplateArgumentLoc> &TempArgs);
QualType CheckTemplateIdType(TemplateName Template,
SourceLocation TemplateLoc,
@@ -2491,7 +2257,6 @@ public:
ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
virtual TypeResult ActOnTagTemplateIdType(TypeResult Type,
@@ -2513,7 +2278,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
@@ -2534,7 +2298,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists);
@@ -2575,7 +2338,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr);
@@ -2595,6 +2357,13 @@ public:
SourceLocation TemplateLoc,
Declarator &D);
+ bool CheckTemplateArgument(NamedDecl *Param,
+ const TemplateArgumentLoc &Arg,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateArgumentListBuilder &Converted);
+
bool CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
@@ -2612,17 +2381,54 @@ public:
DeclaratorInfo *Arg);
bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
NamedDecl *&Entity);
- bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member);
+ bool CheckTemplateArgumentPointerToMember(Expr *Arg,
+ TemplateArgument &Converted);
bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType InstantiatedParamType, Expr *&Arg,
TemplateArgument &Converted);
- bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, DeclRefExpr *Arg);
+ bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+ const TemplateArgumentLoc &Arg);
+
+ /// \brief Enumeration describing how template parameter lists are compared
+ /// for equality.
+ enum TemplateParameterListEqualKind {
+ /// \brief We are matching the template parameter lists of two templates
+ /// that might be redeclarations.
+ ///
+ /// \code
+ /// template<typename T> struct X;
+ /// template<typename T> struct X;
+ /// \endcode
+ TPL_TemplateMatch,
+
+ /// \brief We are matching the template parameter lists of two template
+ /// template parameters as part of matching the template parameter lists
+ /// of two templates that might be redeclarations.
+ ///
+ /// \code
+ /// template<template<int I> class TT> struct X;
+ /// template<template<int Value> class Other> struct X;
+ /// \endcode
+ TPL_TemplateTemplateParmMatch,
+
+ /// \brief We are matching the template parameter lists of a template
+ /// template argument against the template parameter lists of a template
+ /// template parameter.
+ ///
+ /// \code
+ /// template<template<int Value> class Metafun> struct X;
+ /// template<int Value> struct integer_c;
+ /// X<integer_c> xic;
+ /// \endcode
+ TPL_TemplateTemplateArgumentMatch
+ };
+
bool TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
- bool IsTemplateTemplateParm = false,
+ TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc
- = SourceLocation());
+ = SourceLocation());
bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
@@ -2659,6 +2465,11 @@ public:
std::string
getTemplateArgumentBindingsText(const TemplateParameterList *Params,
const TemplateArgumentList &Args);
+
+ std::string
+ getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
/// \brief Describes the result of template argument deduction.
///
@@ -2849,7 +2660,8 @@ public:
// C++ Template Instantiation
//
- MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D);
+ MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D,
+ const TemplateArgumentList *Innermost = 0);
/// \brief A template instantiation that is currently in progress.
struct ActiveTemplateInstantiation {
@@ -2880,17 +2692,30 @@ public:
/// partial specialization or a function template. The
/// Entity is either a ClassTemplatePartialSpecializationDecl or
/// a FunctionTemplateDecl.
- DeducedTemplateArgumentSubstitution
+ DeducedTemplateArgumentSubstitution,
+
+ /// We are substituting prior template arguments into a new
+ /// template parameter. The template parameter itself is either a
+ /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+ PriorTemplateArgumentSubstitution,
+
+ /// We are checking the validity of a default template argument that
+ /// has been used when naming a template-id.
+ DefaultTemplateArgumentChecking
} Kind;
/// \brief The point of instantiation within the source code.
SourceLocation PointOfInstantiation;
+ /// \brief The template in which we are performing the instantiation,
+ /// for substitutions of prior template arguments.
+ TemplateDecl *Template;
+
/// \brief The entity that is being instantiated.
uintptr_t Entity;
- // \brief If this the instantiation of a default template
- // argument, the list of template arguments.
+ /// \brief The list of template arguments we are substituting, if they
+ /// are not part of the entity.
const TemplateArgument *TemplateArgs;
/// \brief The number of template arguments in TemplateArgs.
@@ -2901,9 +2726,14 @@ public:
/// template instantiation.
SourceRange InstantiationRange;
- ActiveTemplateInstantiation() : Kind(TemplateInstantiation), Entity(0),
- TemplateArgs(0), NumTemplateArgs(0) {}
+ ActiveTemplateInstantiation()
+ : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0),
+ NumTemplateArgs(0) {}
+ /// \brief Determines whether this template is an actual instantiation
+ /// that should be counted toward the maximum instantiation depth.
+ bool isInstantiationRecord() const;
+
friend bool operator==(const ActiveTemplateInstantiation &X,
const ActiveTemplateInstantiation &Y) {
if (X.Kind != Y.Kind)
@@ -2916,6 +2746,13 @@ public:
case TemplateInstantiation:
return true;
+ case PriorTemplateArgumentSubstitution:
+ case DefaultTemplateArgumentChecking:
+ if (X.Template != Y.Template)
+ return false;
+
+ // Fall through
+
case DefaultTemplateArgumentInstantiation:
case ExplicitTemplateArgumentSubstitution:
case DeducedTemplateArgumentSubstitution:
@@ -2942,6 +2779,11 @@ public:
llvm::SmallVector<ActiveTemplateInstantiation, 16>
ActiveTemplateInstantiations;
+ /// \brief The number of ActiveTemplateInstantiation entries in
+ /// \c ActiveTemplateInstantiations that are not actual instantiations and,
+ /// therefore, should not be counted as part of the instantiation depth.
+ unsigned NonInstantiationEntries;
+
/// \brief The last template from which a template instantiation
/// error or warning was produced.
///
@@ -3001,6 +2843,32 @@ public:
unsigned NumTemplateArgs,
SourceRange InstantiationRange = SourceRange());
+ /// \brief Note that we are substituting prior template arguments into a
+ /// non-type or template template parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+ /// \brief Note that we are checking the default template argument
+ /// against the template parameter for a given template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NamedDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+
/// \brief Note that we have finished instantiating this template.
void Clear();
@@ -3273,8 +3141,9 @@ public:
SourceLocation CatLoc);
virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
- IdentifierInfo **IdentList,
- unsigned NumElts);
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ unsigned NumElts);
virtual DeclPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
const IdentifierLocPair *IdentList,
@@ -3484,6 +3353,12 @@ public:
/// CompatiblePointerDiscardsQualifiers - The assignment discards
/// c/v/r qualifiers, which we accept as an extension.
CompatiblePointerDiscardsQualifiers,
+
+ /// IncompatibleNestedPointerQualifiers - The assignment is between two
+ /// nested pointer types, and the qualifiers other than the first two
+ /// levels differ e.g. char ** -> const char **, but we accept them as an
+ /// extension.
+ IncompatibleNestedPointerQualifiers,
/// IncompatibleVectors - The assignment is between two vector types that
/// have the same size, which we accept as an extension.
@@ -3555,10 +3430,11 @@ public:
ImplicitConversionSequence& ICS);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const ImplicitConversionSequence& ICS,
- const char *Flavor);
+ const char *Flavor,
+ bool IgnoreBaseAccess = false);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const StandardConversionSequence& SCS,
- const char *Flavor);
+ const char *Flavor, bool IgnoreBaseAccess);
bool BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
const ImplicitConversionSequence& ICS,
@@ -3660,7 +3536,8 @@ public:
bool SuppressUserConversions,
bool AllowExplicit,
bool ForceRValue,
- ImplicitConversionSequence *ICS = 0);
+ ImplicitConversionSequence *ICS = 0,
+ bool IgnoreBaseAccess = false);
/// CheckCastTypes - Check type constraints for casting between types under
/// C semantics, or forward to CXXCheckCStyleCast in C++.
@@ -3745,7 +3622,6 @@ public:
/// \name Code completion
//@{
- void setCodeCompleteConsumer(CodeCompleteConsumer *CCC);
virtual void CodeCompleteOrdinaryName(Scope *S);
virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
SourceLocation OpLoc,
@@ -3763,7 +3639,13 @@ public:
virtual void CodeCompleteOperatorName(Scope *S);
virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS);
- //@}
+ virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
+ SourceLocation FNameLoc);
+ virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver);
+ virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+ unsigned NumProtocols);
+ virtual void CodeCompleteObjCProtocolDecl(Scope *S);
+ //@}
//===--------------------------------------------------------------------===//
// Extra semantic analysis beyond the C type system
@@ -3808,7 +3690,6 @@ private:
void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
};
-
//===--------------------------------------------------------------------===//
// Typed version of Parser::ExprArg (smart pointer for wrapping Expr pointers).
template <typename T>
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 0a5335a2be05..5769716b33ea 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/Expr.h"
using namespace clang;
@@ -179,10 +180,8 @@ void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
for (unsigned i = 0; i < NumIdentifiers; ++i) {
const Token &Tok = Identifiers[i];
IdentifierInfo *Name = Tok.getIdentifierInfo();
- LookupResult Lookup;
- LookupParsedName(Lookup, curScope, NULL, Name,LookupOrdinaryName,
- false, true, Tok.getLocation());
- // FIXME: Handle Lookup.isAmbiguous?
+ LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
+ LookupParsedName(Lookup, curScope, NULL, true);
NamedDecl *ND = Lookup.getAsSingleDecl(Context);
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 76faddaa0384..e5ad338502df 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -70,28 +70,31 @@ static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
- unsigned &msg);
+ unsigned &msg,
+ CastExpr::CastKind &Kind);
static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
- unsigned &msg);
-static TryCastResult TryStaticDowncast(Sema &Self, QualType SrcType,
- QualType DestType, bool CStyle,
+ unsigned &msg,
+ CastExpr::CastKind &Kind);
+static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
+ CanQualType DestType, bool CStyle,
const SourceRange &OpRange,
QualType OrigSrcType,
- QualType OrigDestType, unsigned &msg);
+ QualType OrigDestType, unsigned &msg,
+ CastExpr::CastKind &Kind);
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType,
QualType DestType,bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind);
-static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr,
+static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind,
CXXMethodDecl *&ConversionDecl);
-static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
@@ -187,7 +190,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
assert((DestType->isPointerType() || DestType->isMemberPointerType()) &&
"Destination type is not pointer or pointer to member.");
- QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType;
+ QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
+ UnwrappedDestType = Self.Context.getCanonicalType(DestType);
llvm::SmallVector<Qualifiers, 8> cv1, cv2;
// Find the qualifications.
@@ -385,14 +389,15 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
if (DestType->isVoidType()) {
+ Kind = CastExpr::CK_ToVoid;
return;
}
- if (!DestType->isLValueReferenceType())
+ if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
Self.DefaultFunctionArrayConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
- if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false,OpRange, msg,
+ if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
Kind, ConversionDecl)
!= TC_Success && msg != 0)
Self.Diag(OpRange.getBegin(), msg) << CT_Static
@@ -402,7 +407,7 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// TryStaticCast - Check if a static cast can be performed, and do so if
/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
/// and casting away constness.
-static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange, unsigned &msg,
CastExpr::CastKind &Kind,
@@ -427,15 +432,18 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
// C++ 5.2.9p5, reference downcast.
// See the function for details.
// DR 427 specifies that this is to be applied before paragraph 2.
- tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle,OpRange,msg);
+ tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange,
+ msg, Kind);
if (tcr != TC_NotApplicable)
return tcr;
// N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
// reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg);
- if (tcr != TC_NotApplicable)
+ if (tcr != TC_NotApplicable) {
+ Kind = CastExpr::CK_NoOp;
return tcr;
+ }
// C++ 5.2.9p2: An expression e can be explicitly converted to a type T
// [...] if the declaration "T t(e);" is well-formed, [...].
@@ -467,13 +475,16 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
if (DestType->isEnumeralType()) {
if (SrcType->isComplexType() || SrcType->isVectorType()) {
// Fall through - these cannot be converted.
- } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType())
+ } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) {
+ Kind = CastExpr::CK_IntegralCast;
return TC_Success;
+ }
}
// Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast.
// C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance.
- tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg);
+ tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg,
+ Kind);
if (tcr != TC_NotApplicable)
return tcr;
@@ -500,6 +511,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
msg = diag::err_bad_cxx_cast_const_away;
return TC_Failed;
}
+ Kind = CastExpr::CK_BitCast;
return TC_Success;
}
}
@@ -544,7 +556,7 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
TryCastResult
TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, const SourceRange &OpRange,
- unsigned &msg) {
+ unsigned &msg, CastExpr::CastKind &Kind) {
// C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
// cast to type "reference to cv2 D", where D is a class derived from B,
// if a valid standard conversion from "pointer to D" to "pointer to B"
@@ -567,15 +579,17 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
QualType DestPointee = DestReference->getPointeeType();
- return TryStaticDowncast(Self, SrcExpr->getType(), DestPointee, CStyle,
- OpRange, SrcExpr->getType(), DestType, msg);
+ return TryStaticDowncast(Self,
+ Self.Context.getCanonicalType(SrcExpr->getType()),
+ Self.Context.getCanonicalType(DestPointee), CStyle,
+ OpRange, SrcExpr->getType(), DestType, msg, Kind);
}
/// Tests whether a conversion according to C++ 5.2.9p8 is valid.
TryCastResult
TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
bool CStyle, const SourceRange &OpRange,
- unsigned &msg) {
+ unsigned &msg, CastExpr::CastKind &Kind) {
// C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
// type, can be converted to an rvalue of type "pointer to cv2 D", where D
// is a class derived from B, if a valid standard conversion from "pointer
@@ -595,25 +609,27 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
return TC_NotApplicable;
}
- return TryStaticDowncast(Self, SrcPointer->getPointeeType(),
- DestPointer->getPointeeType(), CStyle,
- OpRange, SrcType, DestType, msg);
+ return TryStaticDowncast(Self,
+ Self.Context.getCanonicalType(SrcPointer->getPointeeType()),
+ Self.Context.getCanonicalType(DestPointer->getPointeeType()),
+ CStyle, OpRange, SrcType, DestType, msg, Kind);
}
/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and
/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to
-/// DestType, both of which must be canonical, is possible and allowed.
+/// DestType is possible and allowed.
TryCastResult
-TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType,
+TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
- QualType OrigDestType, unsigned &msg) {
+ QualType OrigDestType, unsigned &msg,
+ CastExpr::CastKind &Kind) {
// We can only work with complete types. But don't complain if it doesn't work
if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, PDiag(0)) ||
Self.RequireCompleteType(OpRange.getBegin(), DestType, PDiag(0)))
return TC_NotApplicable;
// Downcast can only happen in class hierarchies, so we need classes.
- if (!DestType->isRecordType() || !SrcType->isRecordType()) {
+ if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) {
return TC_NotApplicable;
}
@@ -669,12 +685,13 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType,
EE = PI->rend();
EI != EE; ++EI)
PathDisplayStr += EI->Base->getType().getAsString() + " -> ";
- PathDisplayStr += DestType.getAsString();
+ PathDisplayStr += QualType(DestType).getAsString();
}
}
Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast)
- << SrcType.getUnqualifiedType() << DestType.getUnqualifiedType()
+ << QualType(SrcType).getUnqualifiedType()
+ << QualType(DestType).getUnqualifiedType()
<< PathDisplayStr << OpRange;
msg = 0;
return TC_Failed;
@@ -695,6 +712,7 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType,
return TC_Failed;
}
+ Kind = CastExpr::CK_BaseToDerived;
return TC_Success;
}
@@ -719,10 +737,8 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
}
// T == T, modulo cv
- if (Self.Context.getCanonicalType(
- SrcMemPtr->getPointeeType().getUnqualifiedType()) !=
- Self.Context.getCanonicalType(DestMemPtr->getPointeeType().
- getUnqualifiedType()))
+ if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(),
+ DestMemPtr->getPointeeType()))
return TC_NotApplicable;
// B base of D
@@ -772,7 +788,7 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
/// An expression e can be explicitly converted to a type T using a
/// @c static_cast if the declaration "T t(e);" is well-formed [...].
TryCastResult
-TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
bool CStyle, const SourceRange &OpRange, unsigned &msg,
CastExpr::CastKind &Kind,
CXXMethodDecl *&ConversionDecl) {
@@ -785,27 +801,49 @@ TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType,
}
if (DestType->isReferenceType()) {
+ // All reference bindings insert implicit casts above that do the actual
+ // casting.
+ Kind = CastExpr::CK_NoOp;
+
// At this point of CheckStaticCast, if the destination is a reference,
// this has to work. There is no other way that works.
// On the other hand, if we're checking a C-style cast, we've still got
- // the reinterpret_cast way. In that case, we pass an ICS so we don't
- // get error messages.
- ImplicitConversionSequence ICS;
- bool failed = Self.CheckReferenceInit(SrcExpr, DestType,
- OpRange.getBegin(),
- /*SuppressUserConversions=*/false,
- /*AllowExplicit=*/false,
- /*ForceRValue=*/false,
- CStyle ? &ICS : 0);
- if (!failed)
+ // the reinterpret_cast way. So in C-style mode, we first try the call
+ // with an ICS to suppress errors.
+ if (CStyle) {
+ ImplicitConversionSequence ICS;
+ if(Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(),
+ /*SuppressUserConversions=*/false,
+ /*AllowExplicit=*/false, /*ForceRValue=*/false,
+ &ICS))
+ return TC_NotApplicable;
+ }
+ // Now we're committed either way.
+ if(!Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(),
+ /*SuppressUserConversions=*/false,
+ /*AllowExplicit=*/false,
+ /*ForceRValue=*/false, 0,
+ /*IgnoreBaseAccess=*/CStyle))
return TC_Success;
- if (CStyle)
- return TC_NotApplicable;
- // If we didn't pass the ICS, we already got an error message.
+
+ // We already got an error message.
msg = 0;
return TC_Failed;
}
+ if (DestType->isRecordType()) {
+ if (CXXConstructorDecl *Constructor
+ = Self.TryInitializationByConstructor(DestType, &SrcExpr, 1,
+ OpRange.getBegin(),
+ Sema::IK_Direct)) {
+ ConversionDecl = Constructor;
+ Kind = CastExpr::CK_ConstructorConversion;
+ return TC_Success;
+ }
+
+ return TC_NotApplicable;
+ }
+
// FIXME: To get a proper error from invalid conversions here, we need to
// reimplement more of this.
// FIXME: This does not actually perform the conversion, and thus does not
@@ -821,18 +859,12 @@ TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType,
if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
return TC_NotApplicable;
- if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion) {
- ConversionDecl = cast<CXXMethodDecl>(ICS.UserDefined.ConversionFunction);
- if (isa<CXXConstructorDecl>(ConversionDecl))
- Kind = CastExpr::CK_ConstructorConversion;
- else if (isa<CXXConversionDecl>(ConversionDecl))
- Kind = CastExpr::CK_UserDefinedConversion;
- } else if (ICS.ConversionKind ==
- ImplicitConversionSequence::StandardConversion) {
- // FIXME: Set the cast kind depending on which types of conversions we have.
- }
-
- return TC_Success;
+ // The conversion is possible, so commit to it.
+ Kind = CastExpr::CK_NoOp;
+ msg = 0;
+ return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, "casting",
+ /*IgnoreBaseAccess*/CStyle) ?
+ TC_Failed : TC_Success;
}
/// TryConstCast - See if a const_cast from source to destination is allowed,
@@ -1104,7 +1136,7 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
if (CastTy->isDependentType() || CastExpr->isTypeDependent())
return false;
- if (!CastTy->isLValueReferenceType())
+ if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
DefaultFunctionArrayConversion(CastExpr);
// C++ [expr.cast]p5: The conversions performed by
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index ce3fb5f83c8f..34a5b784d49b 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
@@ -307,8 +308,9 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
if (NNS->getKind() != NestedNameSpecifier::Identifier)
return 0;
- LookupResult Found;
- LookupName(Found, S, NNS->getAsIdentifier(), LookupNestedNameSpecifierName);
+ LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
+ LookupNestedNameSpecifierName);
+ LookupName(Found, S);
assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
NamedDecl *Result = Found.getAsSingleDecl(Context);
@@ -336,6 +338,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
NestedNameSpecifier *Prefix
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+
// Determine where to perform name lookup
DeclContext *LookupCtx = 0;
bool isDependent = false;
@@ -350,9 +354,10 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// so long into the context associated with the prior nested-name-specifier.
LookupCtx = computeDeclContext(SS, EnteringContext);
isDependent = isDependentScopeSpecifier(SS);
+ Found.setContextRange(SS.getRange());
}
- LookupResult Found;
+
bool ObjectTypeSearchedInScope = false;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
@@ -364,10 +369,9 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS))
return 0;
- LookupQualifiedName(Found, LookupCtx, &II, LookupNestedNameSpecifierName,
- false);
+ LookupQualifiedName(Found, LookupCtx);
- if (!ObjectType.isNull() && Found.getKind() == LookupResult::NotFound) {
+ if (!ObjectType.isNull() && Found.empty()) {
// C++ [basic.lookup.classref]p4:
// If the id-expression in a class member access is a qualified-id of
// the form
@@ -389,7 +393,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// reconstruct the result from when name lookup was performed at template
// definition time.
if (S)
- LookupName(Found, S, &II, LookupNestedNameSpecifierName);
+ LookupName(Found, S);
else if (ScopeLookupResult)
Found.addDecl(ScopeLookupResult);
@@ -406,7 +410,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
return NestedNameSpecifier::Create(Context, Prefix, &II);
} else {
// Perform unqualified name lookup in the current scope.
- LookupName(Found, S, &II, LookupNestedNameSpecifierName);
+ LookupName(Found, S);
}
// FIXME: Deal with ambiguities cleanly.
@@ -423,9 +427,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// scope, reconstruct the result from the template instantiation itself.
NamedDecl *OuterDecl;
if (S) {
- LookupResult FoundOuter;
- LookupName(FoundOuter, S, &II, LookupNestedNameSpecifierName);
- // FIXME: Handle ambiguities!
+ LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+ LookupName(FoundOuter, S);
OuterDecl = FoundOuter.getAsSingleDecl(Context);
} else
OuterDecl = ScopeLookupResult;
@@ -467,8 +470,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// ordinary name lookup, which can help us produce better error
// messages.
if (!SD) {
- Found.clear();
- LookupName(Found, S, &II, LookupOrdinaryName);
+ Found.clear(LookupOrdinaryName);
+ LookupName(Found, S);
SD = Found.getAsSingleDecl(Context);
}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 38b6ebeefab9..9060fe6ab742 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -91,6 +91,12 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
if (Format->getType() == "printf0") {
// printf0 allows null "format" string; if so don't check format/args
unsigned format_idx = Format->getFormatIdx() - 1;
+ // Does the index refer to the implicit object argument?
+ if (isa<CXXMemberCallExpr>(TheCall)) {
+ if (format_idx == 0)
+ return false;
+ --format_idx;
+ }
if (format_idx < TheCall->getNumArgs()) {
Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts();
if (!Format->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
@@ -204,7 +210,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
if (!HasVAListArg) {
if (const FunctionProtoType *Proto
= FDecl->getType()->getAs<FunctionProtoType>())
- HasVAListArg = !Proto->isVariadic();
+ HasVAListArg = !Proto->isVariadic();
}
CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
HasVAListArg ? 0 : Format->getFirstArg() - 1);
@@ -628,8 +634,7 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
return ExprError();
}
- if (Context.getCanonicalType(FAType).getUnqualifiedType() !=
- Context.getCanonicalType(SAType).getUnqualifiedType()) {
+ if (!Context.hasSameUnqualifiedType(FAType, SAType)) {
Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
<< SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd());
@@ -971,6 +976,18 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg) {
const Expr *Fn = TheCall->getCallee();
+ // The way the format attribute works in GCC, the implicit this argument
+ // of member functions is counted. However, it doesn't appear in our own
+ // lists, so decrement format_idx in that case.
+ if (isa<CXXMemberCallExpr>(TheCall)) {
+ // Catch a format attribute mistakenly referring to the object argument.
+ if (format_idx == 0)
+ return;
+ --format_idx;
+ if(firstDataArg != 0)
+ --firstDataArg;
+ }
+
// CHECK: printf-like function is called with no format string.
if (format_idx >= TheCall->getNumArgs()) {
Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string)
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index e9df17d6a115..9cecdadc867e 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -13,6 +13,7 @@
#include "Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -23,13 +24,6 @@
using namespace clang;
-/// \brief Set the code-completion consumer for semantic analysis.
-void Sema::setCodeCompleteConsumer(CodeCompleteConsumer *CCC) {
- assert(((CodeCompleter != 0) != (CCC != 0)) &&
- "Already set or cleared a code-completion consumer?");
- CodeCompleter = CCC;
-}
-
namespace {
/// \brief A container of code-completion results.
class ResultBuilder {
@@ -101,6 +95,9 @@ namespace {
/// \brief Exit from the current scope.
void ExitScope();
+ /// \brief Ignore this declaration, if it is seen again.
+ void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
+
/// \name Name lookup predicates
///
/// These predicates can be passed to the name lookup functions to filter the
@@ -187,8 +184,7 @@ getRequiredQualification(ASTContext &Context,
Context.getTypeDeclType(TD).getTypePtr());
else
assert(Parent->isTranslationUnit());
- }
-
+ }
return Result;
}
@@ -206,7 +202,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
return;
// Look through using declarations.
- if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration))
+ if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration))
MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier),
CurContext);
@@ -474,17 +470,24 @@ static unsigned CollectMemberLookupResults(DeclContext *Ctx,
for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
CurCtx = CurCtx->getNextContext()) {
for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
- DEnd = CurCtx->decls_end();
+ DEnd = CurCtx->decls_end();
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
Results.MaybeAddResult(Result(ND, Rank, 0, InBaseClass), CurContext);
+
+ // Visit transparent contexts inside this context.
+ if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
+ if (InnerCtx->isTransparentContext())
+ CollectMemberLookupResults(InnerCtx, Rank, CurContext, Visited,
+ Results, InBaseClass);
+ }
}
}
// Traverse the contexts of inherited classes.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
- BEnd = Record->bases_end();
+ BEnd = Record->bases_end();
B != BEnd; ++B) {
QualType BaseType = B->getType();
@@ -674,6 +677,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank,
static void AddFunctionParameterChunks(ASTContext &Context,
FunctionDecl *Function,
CodeCompletionString *Result) {
+ typedef CodeCompletionString::Chunk Chunk;
+
CodeCompletionString *CCStr = Result;
for (unsigned P = 0, N = Function->getNumParams(); P != N; ++P) {
@@ -688,7 +693,7 @@ static void AddFunctionParameterChunks(ASTContext &Context,
}
if (P != 0)
- CCStr->AddTextChunk(", ");
+ CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
// Format the placeholder string.
std::string PlaceholderStr;
@@ -713,6 +718,8 @@ static void AddTemplateParameterChunks(ASTContext &Context,
TemplateDecl *Template,
CodeCompletionString *Result,
unsigned MaxParameters = 0) {
+ typedef CodeCompletionString::Chunk Chunk;
+
CodeCompletionString *CCStr = Result;
bool FirstParameter = true;
@@ -768,7 +775,7 @@ static void AddTemplateParameterChunks(ASTContext &Context,
if (FirstParameter)
FirstParameter = false;
else
- CCStr->AddTextChunk(", ");
+ CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
// Add the placeholder string.
CCStr->AddPlaceholderChunk(PlaceholderStr.c_str());
@@ -803,6 +810,8 @@ void AddQualifierToCompletionString(CodeCompletionString *Result,
/// result is all that is needed.
CodeCompletionString *
CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
+ typedef CodeCompletionString::Chunk Chunk;
+
if (Kind == RK_Keyword)
return 0;
@@ -813,12 +822,12 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
// Format a function-like macro with placeholders for the arguments.
CodeCompletionString *Result = new CodeCompletionString;
- Result->AddTextChunk(Macro->getName().str().c_str());
- Result->AddTextChunk("(");
+ Result->AddTypedTextChunk(Macro->getName().str().c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
A != AEnd; ++A) {
if (A != MI->arg_begin())
- Result->AddTextChunk(", ");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
if (!MI->isVariadic() || A != AEnd - 1) {
// Non-variadic argument.
@@ -837,21 +846,28 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
Result->AddPlaceholderChunk(Arg.c_str());
}
}
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
assert(Kind == RK_Declaration && "Missed a macro kind?");
NamedDecl *ND = Declaration;
+ if (StartsNestedNameSpecifier) {
+ CodeCompletionString *Result = new CodeCompletionString;
+ Result->AddTypedTextChunk(ND->getNameAsString().c_str());
+ Result->AddTextChunk("::");
+ return Result;
+ }
+
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
CodeCompletionString *Result = new CodeCompletionString;
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
- Result->AddTextChunk(Function->getNameAsString().c_str());
- Result->AddTextChunk("(");
+ Result->AddTypedTextChunk(Function->getNameAsString().c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
AddFunctionParameterChunks(S.Context, Function, Result);
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -860,7 +876,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
- Result->AddTextChunk(Function->getNameAsString().c_str());
+ Result->AddTypedTextChunk(Function->getNameAsString().c_str());
// Figure out which template parameters are deduced (or have default
// arguments).
@@ -884,7 +900,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
else {
assert(isa<TemplateTemplateParmDecl>(Param));
HasDefaultArg
- = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
+ = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
}
if (!HasDefaultArg)
@@ -896,16 +912,16 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
// Some of the function template arguments cannot be deduced from a
// function call, so we introduce an explicit template argument list
// containing all of the arguments up to the first deducible argument.
- Result->AddTextChunk("<");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
AddTemplateParameterChunks(S.Context, FunTmpl, Result,
LastDeducibleArgument);
- Result->AddTextChunk(">");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
}
// Add the function parameters
- Result->AddTextChunk("(");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
AddFunctionParameterChunks(S.Context, Function, Result);
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -913,20 +929,51 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
CodeCompletionString *Result = new CodeCompletionString;
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
- Result->AddTextChunk(Template->getNameAsString().c_str());
- Result->AddTextChunk("<");
+ Result->AddTypedTextChunk(Template->getNameAsString().c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
AddTemplateParameterChunks(S.Context, Template, Result);
- Result->AddTextChunk(">");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
return Result;
}
- if (Qualifier || StartsNestedNameSpecifier) {
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+ CodeCompletionString *Result = new CodeCompletionString;
+ Selector Sel = Method->getSelector();
+ if (Sel.isUnarySelector()) {
+ Result->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName());
+ return Result;
+ }
+
+ Result->AddTypedTextChunk(
+ Sel.getIdentifierInfoForSlot(0)->getName().str() + std::string(":"));
+ unsigned Idx = 0;
+ for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; (void)++P, ++Idx) {
+ if (Idx > 0) {
+ std::string Keyword = " ";
+ if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
+ Keyword += II->getName().str();
+ Keyword += ":";
+ Result->AddTextChunk(Keyword);
+ }
+
+ std::string Arg;
+ (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
+ Arg = "(" + Arg + ")";
+ if (IdentifierInfo *II = (*P)->getIdentifier())
+ Arg += II->getName().str();
+ Result->AddPlaceholderChunk(Arg);
+ }
+
+ return Result;
+ }
+
+ if (Qualifier) {
CodeCompletionString *Result = new CodeCompletionString;
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
- Result->AddTextChunk(ND->getNameAsString().c_str());
- if (StartsNestedNameSpecifier)
- Result->AddTextChunk("::");
+ Result->AddTypedTextChunk(ND->getNameAsString().c_str());
return Result;
}
@@ -937,6 +984,8 @@ CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
unsigned CurrentArg,
Sema &S) const {
+ typedef CodeCompletionString::Chunk Chunk;
+
CodeCompletionString *Result = new CodeCompletionString;
FunctionDecl *FDecl = getFunction();
const FunctionProtoType *Proto
@@ -947,9 +996,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
const FunctionType *FT = getFunctionType();
Result->AddTextChunk(
FT->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
- Result->AddTextChunk("(");
- Result->AddPlaceholderChunk("...");
- Result->AddTextChunk("(");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -959,11 +1008,11 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Result->AddTextChunk(
Proto->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
- Result->AddTextChunk("(");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
for (unsigned I = 0; I != NumParams; ++I) {
if (I)
- Result->AddTextChunk(", ");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
std::string ArgString;
QualType ArgType;
@@ -978,19 +1027,20 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
if (I == CurrentArg)
- Result->AddPlaceholderChunk(ArgString.c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
+ ArgString.c_str()));
else
Result->AddTextChunk(ArgString.c_str());
}
if (Proto && Proto->isVariadic()) {
- Result->AddTextChunk(", ");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
if (CurrentArg < NumParams)
Result->AddTextChunk("...");
else
- Result->AddPlaceholderChunk("...");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
}
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -1000,7 +1050,9 @@ namespace {
typedef CodeCompleteConsumer::Result Result;
bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const {
- if (X.getNameKind() != Y.getNameKind())
+ if (!X.getObjCSelector().isNull() && !Y.getObjCSelector().isNull()) {
+ // Consider all selector kinds to be equivalent.
+ } else if (X.getNameKind() != Y.getNameKind())
return X.getNameKind() < Y.getNameKind();
return llvm::LowercaseString(X.getAsString())
@@ -1049,32 +1101,77 @@ namespace {
};
}
-// Add all of the known macros as code-completion results.
static void AddMacroResults(Preprocessor &PP, unsigned Rank,
ResultBuilder &Results) {
Results.EnterNewScope();
- for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end();
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
+ MEnd = PP.macro_end();
M != MEnd; ++M)
Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank));
Results.ExitScope();
}
-static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
- CodeCompleteConsumer::Result *Results,
- unsigned NumResults) {
+static void HandleCodeCompleteResults(Sema *S,
+ CodeCompleteConsumer *CodeCompleter,
+ CodeCompleteConsumer::Result *Results,
+ unsigned NumResults) {
// Sort the results by rank/kind/etc.
std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult());
if (CodeCompleter)
- CodeCompleter->ProcessCodeCompleteResults(Results, NumResults);
+ CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults);
}
void Sema::CodeCompleteOrdinaryName(Scope *S) {
ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
0, CurContext, Results);
- AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+static void AddObjCProperties(ObjCContainerDecl *Container,
+ DeclContext *CurContext,
+ ResultBuilder &Results) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ // Add properties in this container.
+ for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
+ PEnd = Container->prop_end();
+ P != PEnd;
+ ++P)
+ Results.MaybeAddResult(Result(*P, 0), CurContext);
+
+ // Add properties in referenced protocols.
+ if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+ for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
+ PEnd = Protocol->protocol_end();
+ P != PEnd; ++P)
+ AddObjCProperties(*P, CurContext, Results);
+ } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
+ // Look through categories.
+ for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ AddObjCProperties(Category, CurContext, Results);
+
+ // Look through protocols.
+ for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
+ E = IFace->protocol_end();
+ I != E; ++I)
+ AddObjCProperties(*I, CurContext, Results);
+
+ // Look in the superclass.
+ if (IFace->getSuperClass())
+ AddObjCProperties(IFace->getSuperClass(), CurContext, Results);
+ } else if (const ObjCCategoryDecl *Category
+ = dyn_cast<ObjCCategoryDecl>(Container)) {
+ // Look through protocols.
+ for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(),
+ PEnd = Category->protocol_end();
+ P != PEnd; ++P)
+ AddObjCProperties(*P, CurContext, Results);
+ }
}
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
@@ -1099,11 +1196,13 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
ResultBuilder Results(*this, &ResultBuilder::IsMember);
unsigned NextRank = 0;
-
+
+ Results.EnterNewScope();
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
- NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
+ // Access to a C/C++ class, struct, or union.
+ NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
Record->getDecl(), Results);
-
+
if (getLangOptions().CPlusPlus) {
if (!Results.empty()) {
// The "template" keyword can follow "->" or "." in the grammar.
@@ -1117,27 +1216,63 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
break;
}
}
-
+
if (IsDependent)
Results.MaybeAddResult(Result("template", NextRank++));
}
-
+
// We could have the start of a nested-name-specifier. Add those
// results as well.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
+ CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
CurContext, Results);
}
+ } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
+ // Objective-C property reference.
- // Add macros
- AddMacroResults(PP, NextRank, Results);
+ // Add property results based on our interface.
+ const ObjCObjectPointerType *ObjCPtr
+ = BaseType->getAsObjCInterfacePointerType();
+ assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
+ AddObjCProperties(ObjCPtr->getInterfaceDecl(), CurContext, Results);
- // Hand off the results found for code completion.
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ // Add properties from the protocols in a qualified interface.
+ for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
+ E = ObjCPtr->qual_end();
+ I != E; ++I)
+ AddObjCProperties(*I, CurContext, Results);
- // We're done!
- return;
+ // FIXME: We could (should?) also look for "implicit" properties, identified
+ // only by the presence of nullary and unary selectors.
+ } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+ (!IsArrow && BaseType->isObjCInterfaceType())) {
+ // Objective-C instance variable access.
+ ObjCInterfaceDecl *Class = 0;
+ if (const ObjCObjectPointerType *ObjCPtr
+ = BaseType->getAs<ObjCObjectPointerType>())
+ Class = ObjCPtr->getInterfaceDecl();
+ else
+ Class = BaseType->getAs<ObjCInterfaceType>()->getDecl();
+
+ // Add all ivars from this class and its superclasses.
+ for (; Class; Class = Class->getSuperClass()) {
+ for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
+ IVarEnd = Class->ivar_end();
+ IVar != IVarEnd; ++IVar)
+ Results.MaybeAddResult(Result(*IVar, 0), CurContext);
+ }
}
+
+ // FIXME: How do we cope with isa?
+
+ Results.ExitScope();
+
+ // Add macros
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+
+ // Hand off the results found for code completion.
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
@@ -1177,8 +1312,9 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
NextRank, CurContext, Results);
}
- AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteCase(Scope *S) {
@@ -1255,8 +1391,9 @@ void Sema::CodeCompleteCase(Scope *S) {
}
Results.ExitScope();
- AddMacroResults(PP, 1, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, 1, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
namespace {
@@ -1328,7 +1465,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
if (Cand->Viable)
Results.push_back(ResultCandidate(Cand->Function));
}
- CodeCompleter->ProcessOverloadCandidates(NumArgs, Results.data(),
+ CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
Results.size());
}
@@ -1350,8 +1487,9 @@ void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
if (!Results.empty() && NNS->isDependent())
Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank));
- AddMacroResults(PP, NextRank + 1, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank + 1, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteUsing(Scope *S) {
@@ -1371,8 +1509,9 @@ void Sema::CodeCompleteUsing(Scope *S) {
0, CurContext, Results);
Results.ExitScope();
- AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteUsingDirective(Scope *S) {
@@ -1386,8 +1525,9 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
0, CurContext, Results);
Results.ExitScope();
- AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteNamespaceDecl(Scope *S) {
@@ -1421,8 +1561,9 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Results.ExitScope();
}
- AddMacroResults(PP, 1, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, 1, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
@@ -1433,8 +1574,9 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
0, CurContext, Results);
- AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteOperatorName(Scope *S) {
@@ -1464,8 +1606,9 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
NextRank + 1, CurContext, Results);
Results.ExitScope();
- AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) {
@@ -1493,5 +1636,252 @@ void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) {
if (!(Attributes & ObjCDeclSpec::DQ_PR_getter))
Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0));
Results.ExitScope();
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+/// \brief Add all of the Objective-C methods in the given Objective-C
+/// container to the set of results.
+///
+/// The container will be a class, protocol, category, or implementation of
+/// any of the above. This mether will recurse to include methods from
+/// the superclasses of classes along with their categories, protocols, and
+/// implementations.
+///
+/// \param Container the container in which we'll look to find methods.
+///
+/// \param WantInstance whether to add instance methods (only); if false, this
+/// routine will add factory methods (only).
+///
+/// \param CurContext the context in which we're performing the lookup that
+/// finds methods.
+///
+/// \param Results the structure into which we'll add results.
+static void AddObjCMethods(ObjCContainerDecl *Container,
+ bool WantInstanceMethods,
+ DeclContext *CurContext,
+ ResultBuilder &Results) {
+ typedef CodeCompleteConsumer::Result Result;
+ for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+ MEnd = Container->meth_end();
+ M != MEnd; ++M) {
+ if ((*M)->isInstanceMethod() == WantInstanceMethods)
+ Results.MaybeAddResult(Result(*M, 0), CurContext);
+ }
+
+ ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
+ if (!IFace)
+ return;
+
+ // Add methods in protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ AddObjCMethods(*I, WantInstanceMethods, CurContext, Results);
+
+ // Add methods in categories.
+ for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
+ CatDecl = CatDecl->getNextClassCategory()) {
+ AddObjCMethods(CatDecl, WantInstanceMethods, CurContext, Results);
+
+ // Add a categories protocol methods.
+ const ObjCList<ObjCProtocolDecl> &Protocols
+ = CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ AddObjCMethods(*I, WantInstanceMethods, CurContext, Results);
+
+ // Add methods in category implementations.
+ if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
+ AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results);
+ }
+
+ // Add methods in superclass.
+ if (IFace->getSuperClass())
+ AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, CurContext,
+ Results);
+
+ // Add methods in our implementation, if any.
+ if (ObjCImplementationDecl *Impl = IFace->getImplementation())
+ AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results);
+}
+
+void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
+ SourceLocation FNameLoc) {
+ typedef CodeCompleteConsumer::Result Result;
+ ObjCInterfaceDecl *CDecl = 0;
+
+ if (FName->isStr("super")) {
+ // We're sending a message to "super".
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+ // Figure out which interface we're in.
+ CDecl = CurMethod->getClassInterface();
+ if (!CDecl)
+ return;
+
+ // Find the superclass of this class.
+ CDecl = CDecl->getSuperClass();
+ if (!CDecl)
+ return;
+
+ if (CurMethod->isInstanceMethod()) {
+ // We are inside an instance method, which means that the message
+ // send [super ...] is actually calling an instance method on the
+ // current object. Build the super expression and handle this like
+ // an instance method.
+ QualType SuperTy = Context.getObjCInterfaceType(CDecl);
+ SuperTy = Context.getObjCObjectPointerType(SuperTy);
+ OwningExprResult Super
+ = Owned(new (Context) ObjCSuperExpr(FNameLoc, SuperTy));
+ return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get());
+ }
+
+ // Okay, we're calling a factory method in our superclass.
+ }
+ }
+
+ // If the given name refers to an interface type, retrieve the
+ // corresponding declaration.
+ if (!CDecl)
+ if (TypeTy *Ty = getTypeName(*FName, FNameLoc, S, 0, false)) {
+ QualType T = GetTypeFromParser(Ty, 0);
+ if (!T.isNull())
+ if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>())
+ CDecl = Interface->getDecl();
+ }
+
+ if (!CDecl && FName->isStr("super")) {
+ // "super" may be the name of a variable, in which case we are
+ // probably calling an instance method.
+ OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName,
+ false, 0, false);
+ return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get());
+ }
+
+ // Add all of the factory methods in this Objective-C class, its protocols,
+ // superclasses, categories, implementation, etc.
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+ AddObjCMethods(CDecl, false, CurContext, Results);
+ Results.ExitScope();
+
+ // This also suppresses remaining diagnostics.
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ Expr *RecExpr = static_cast<Expr *>(Receiver);
+ QualType RecType = RecExpr->getType();
+
+ // If necessary, apply function/array conversion to the receiver.
+ // C99 6.7.5.3p[7,8].
+ DefaultFunctionArrayConversion(RecExpr);
+ QualType ReceiverType = RecExpr->getType();
+
+ if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) {
+ // FIXME: We're messaging 'id'. Do we actually want to look up every method
+ // in the universe?
+ return;
+ }
+
+ // Build the set of methods we can see.
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Handle messages to Class. This really isn't a message to an instance
+ // method, so we treat it the same way we would treat a message send to a
+ // class method.
+ if (ReceiverType->isObjCClassType() ||
+ ReceiverType->isObjCQualifiedClassType()) {
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+ if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
+ AddObjCMethods(ClassDecl, false, CurContext, Results);
+ }
+ }
+ // Handle messages to a qualified ID ("id<foo>").
+ else if (const ObjCObjectPointerType *QualID
+ = ReceiverType->getAsObjCQualifiedIdType()) {
+ // Search protocols for instance methods.
+ for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
+ E = QualID->qual_end();
+ I != E; ++I)
+ AddObjCMethods(*I, true, CurContext, Results);
+ }
+ // Handle messages to a pointer to interface type.
+ else if (const ObjCObjectPointerType *IFacePtr
+ = ReceiverType->getAsObjCInterfacePointerType()) {
+ // Search the class, its superclasses, etc., for instance methods.
+ AddObjCMethods(IFacePtr->getInterfaceDecl(), true, CurContext, Results);
+
+ // Search protocols for instance methods.
+ for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
+ E = IFacePtr->qual_end();
+ I != E; ++I)
+ AddObjCMethods(*I, true, CurContext, Results);
+ }
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+/// \brief Add all of the protocol declarations that we find in the given
+/// (translation unit) context.
+static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
+ bool OnlyForwardDeclarations,
+ ResultBuilder &Results) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ for (DeclContext::decl_iterator D = Ctx->decls_begin(),
+ DEnd = Ctx->decls_end();
+ D != DEnd; ++D) {
+ // Record any protocols we find.
+ if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
+ if (!OnlyForwardDeclarations || Proto->isForwardDecl())
+ Results.MaybeAddResult(Result(Proto, 0), CurContext);
+
+ // Record any forward-declared protocols we find.
+ if (ObjCForwardProtocolDecl *Forward
+ = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
+ for (ObjCForwardProtocolDecl::protocol_iterator
+ P = Forward->protocol_begin(),
+ PEnd = Forward->protocol_end();
+ P != PEnd; ++P)
+ if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
+ Results.MaybeAddResult(Result(*P, 0), CurContext);
+ }
+ }
+}
+
+void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+ unsigned NumProtocols) {
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Tell the result set to ignore all of the protocols we have
+ // already seen.
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first))
+ Results.Ignore(Protocol);
+
+ // Add all protocols.
+ AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
+ Results);
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Add all protocols.
+ AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
+ Results);
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index d89cb5fc97f5..57c101bd32ce 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -24,6 +25,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Template.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -86,13 +88,14 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
II, SS->getRange()).getAsOpaquePtr();
}
- LookupResult Result;
- LookupParsedName(Result, S, SS, &II, LookupOrdinaryName, false, false);
+ LookupResult Result(*this, &II, NameLoc, LookupOrdinaryName);
+ LookupParsedName(Result, S, SS, false);
NamedDecl *IIDecl = 0;
- switch (Result.getKind()) {
+ switch (Result.getResultKind()) {
case LookupResult::NotFound:
case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue:
return 0;
case LookupResult::Ambiguous:
@@ -101,8 +104,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// diagnose the error then. If we don't do this, then the error
// about hiding the type will be immediately followed by an error
// that only makes sense if the identifier was treated like a type.
- if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding)
+ if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) {
+ Result.suppressDiagnostics();
return 0;
+ }
// Look to see if we have a type anywhere in the list of results.
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
@@ -122,6 +127,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// perform this lookup again (e.g., as an object name), which
// will produce the ambiguity, or will complain that it expected
// a type name.
+ Result.suppressDiagnostics();
return 0;
}
@@ -129,7 +135,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// ambiguity and then return that type. This might be the right
// answer, or it might not be, but it suppresses any attempt to
// perform the name lookup again.
- DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc);
break;
case LookupResult::Found:
@@ -142,7 +147,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
QualType T;
if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
DiagnoseUseOfDecl(IIDecl, NameLoc);
-
+
// C++ [temp.local]p2:
// Within the scope of a class template specialization or
// partial specialization, when the injected-class-name is
@@ -162,10 +167,16 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
T = getQualifiedNameType(*SS, T);
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
- DiagnoseUseOfDecl(IIDecl, NameLoc);
T = Context.getObjCInterfaceType(IDecl);
- } else
+ } else if (UnresolvedUsingTypenameDecl *UUDecl =
+ dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) {
+ // FIXME: preserve source structure information.
+ T = Context.getTypenameType(UUDecl->getTargetNestedNameSpecifier(), &II);
+ } else {
+ // If it's not plausibly a type, suppress diagnostics.
+ Result.suppressDiagnostics();
return 0;
+ }
return T.getAsOpaquePtr();
}
@@ -177,9 +188,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
/// where the user forgot to specify the tag.
DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
// Do a tag name lookup in this scope.
- LookupResult R;
- LookupName(R, S, &II, LookupTagName, false, false);
- if (R.getKind() == LookupResult::Found)
+ LookupResult R(*this, &II, SourceLocation(), LookupTagName);
+ LookupName(R, S, false);
+ R.suppressDiagnostics();
+ if (R.getResultKind() == LookupResult::Found)
if (const TagDecl *TD = dyn_cast<TagDecl>(R.getAsSingleDecl(Context))) {
switch (TD->getTagKind()) {
case TagDecl::TK_struct: return DeclSpec::TST_struct;
@@ -384,6 +396,26 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
return IdResolver.isDeclInScope(D, Ctx, Context, S);
}
+static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
+ if (D->isUsed() || D->hasAttr<UnusedAttr>())
+ return false;
+
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (!RD->hasTrivialConstructor())
+ return false;
+ if (!RD->hasTrivialDestructor())
+ return false;
+ }
+ }
+ }
+
+ return (isa<VarDecl>(D) && !isa<ParmVarDecl>(D) &&
+ !isa<ImplicitParamDecl>(D) &&
+ D->getDeclContext()->isFunctionOrMethod());
+}
+
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
@@ -400,10 +432,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (!D->getDeclName()) continue;
// Diagnose unused variables in this scope.
- if (!D->isUsed() && !D->hasAttr<UnusedAttr>() && isa<VarDecl>(D) &&
- !isa<ParmVarDecl>(D) && !isa<ImplicitParamDecl>(D) &&
- D->getDeclContext()->isFunctionOrMethod())
- Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName();
+ if (ShouldDiagnoseUnusedDecl(D))
+ Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName();
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
@@ -1396,9 +1426,9 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
FEnd = AnonRecord->field_end();
F != FEnd; ++F) {
if ((*F)->getDeclName()) {
- LookupResult R;
- LookupQualifiedName(R, Owner, (*F)->getDeclName(),
- LookupOrdinaryName, true);
+ LookupResult R(*this, (*F)->getDeclName(), SourceLocation(),
+ LookupOrdinaryName, ForRedeclaration);
+ LookupQualifiedName(R, Owner);
NamedDecl *PrevDecl = R.getAsSingleDecl(Context);
if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
// C++ [class.union]p2:
@@ -1651,7 +1681,7 @@ DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
case UnqualifiedId::IK_TemplateId: {
TemplateName TName
- = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
+ = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
if (TemplateDecl *Template = TName.getAsTemplateDecl())
return Template->getDeclName();
if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
@@ -1679,9 +1709,8 @@ static bool isNearlyMatchingFunction(ASTContext &Context,
QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType();
QualType DefParamTy = Definition->getParamDecl(Idx)->getType();
- DeclParamTy = Context.getCanonicalType(DeclParamTy.getNonReferenceType());
- DefParamTy = Context.getCanonicalType(DefParamTy.getNonReferenceType());
- if (DeclParamTy.getUnqualifiedType() != DefParamTy.getUnqualifiedType())
+ if (!Context.hasSameUnqualifiedType(DeclParamTy.getNonReferenceType(),
+ DefParamTy.getNonReferenceType()))
return false;
}
@@ -1766,10 +1795,10 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
NameKind = LookupRedeclarationWithLinkage;
DC = CurContext;
- LookupResult R;
- LookupName(R, S, Name, NameKind, true,
- NameKind == LookupRedeclarationWithLinkage,
- D.getIdentifierLoc());
+ LookupResult R(*this, Name, D.getIdentifierLoc(), NameKind,
+ ForRedeclaration);
+
+ LookupName(R, S, NameKind == LookupRedeclarationWithLinkage);
PrevDecl = R.getAsSingleDecl(Context);
} else { // Something like "int foo::x;"
DC = computeDeclContext(D.getCXXScopeSpec(), true);
@@ -1790,8 +1819,9 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
RequireCompleteDeclContext(D.getCXXScopeSpec()))
return DeclPtrTy();
- LookupResult Res;
- LookupQualifiedName(Res, DC, Name, LookupOrdinaryName, true);
+ LookupResult Res(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+ ForRedeclaration);
+ LookupQualifiedName(Res, DC);
PrevDecl = Res.getAsSingleDecl(Context);
// C++ 7.3.1.2p2:
@@ -1821,17 +1851,22 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
if (isa<TranslationUnitDecl>(DC)) {
Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope)
<< Name << D.getCXXScopeSpec().getRange();
- } else if (!CurContext->Encloses(DC)) {
- // The qualifying scope doesn't enclose the original declaration.
- // Emit diagnostic based on current scope.
- SourceLocation L = D.getIdentifierLoc();
- SourceRange R = D.getCXXScopeSpec().getRange();
- if (isa<FunctionDecl>(CurContext))
- Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
- else
- Diag(L, diag::err_invalid_declarator_scope)
- << Name << cast<NamedDecl>(DC) << R;
- D.setInvalidType();
+ } else {
+ DeclContext *Cur = CurContext;
+ while (isa<LinkageSpecDecl>(Cur))
+ Cur = Cur->getParent();
+ if (!Cur->Encloses(DC)) {
+ // The qualifying scope doesn't enclose the original declaration.
+ // Emit diagnostic based on current scope.
+ SourceLocation L = D.getIdentifierLoc();
+ SourceRange R = D.getCXXScopeSpec().getRange();
+ if (isa<FunctionDecl>(Cur))
+ Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
+ else
+ Diag(L, diag::err_invalid_declarator_scope)
+ << Name << cast<NamedDecl>(DC) << R;
+ D.setInvalidType();
+ }
}
}
@@ -2417,7 +2452,9 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
}
static bool isUsingDecl(Decl *D) {
- return isa<UsingDecl>(D) || isa<UnresolvedUsingDecl>(D);
+ return isa<UsingDecl>(D) ||
+ isa<UnresolvedUsingTypenameDecl>(D) ||
+ isa<UnresolvedUsingValueDecl>(D);
}
/// \brief Data used with FindOverriddenMethod
@@ -2429,7 +2466,7 @@ struct FindOverriddenMethodData {
/// \brief Member lookup function that determines whether a given C++
/// method overrides a method in a base class, to be used with
/// CXXRecordDecl::lookupInBases().
-static bool FindOverriddenMethod(CXXBaseSpecifier *Specifier,
+static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *UserData) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
@@ -2588,12 +2625,27 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
return 0;
}
+ bool isStatic = SC == FunctionDecl::Static;
+
+ // [class.free]p1:
+ // Any allocation function for a class T is a static member
+ // (even if not explicitly declared static).
+ if (Name.getCXXOverloadedOperator() == OO_New ||
+ Name.getCXXOverloadedOperator() == OO_Array_New)
+ isStatic = true;
+
+ // [class.free]p6 Any deallocation function for a class X is a static member
+ // (even if not explicitly declared static).
+ if (Name.getCXXOverloadedOperator() == OO_Delete ||
+ Name.getCXXOverloadedOperator() == OO_Array_Delete)
+ isStatic = true;
+
// This is a C++ method declaration.
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
D.getIdentifierLoc(), Name, R, DInfo,
- (SC == FunctionDecl::Static), isInline);
+ isStatic, isInline);
- isVirtualOkay = (SC != FunctionDecl::Static);
+ isVirtualOkay = !isStatic;
} else {
// Determine whether the function was written with a
// prototype. This true when:
@@ -2812,10 +2864,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateArgs);
TemplateArgsPtr.release();
@@ -2887,8 +2937,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< Name << DC << D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
- LookupResult Prev;
- LookupQualifiedName(Prev, DC, Name, LookupOrdinaryName, true);
+ LookupResult Prev(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+ ForRedeclaration);
+ LookupQualifiedName(Prev, DC);
assert(!Prev.isAmbiguous() &&
"Cannot have an ambiguity in previous-declaration lookup");
for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
@@ -3068,9 +3119,13 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
// C++-specific checks.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
CheckConstructor(Constructor);
- } else if (isa<CXXDestructorDecl>(NewFD)) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
+ } else if (CXXDestructorDecl *Destructor =
+ dyn_cast<CXXDestructorDecl>(NewFD)) {
+ CXXRecordDecl *Record = Destructor->getParent();
QualType ClassType = Context.getTypeDeclType(Record);
+
+ // FIXME: Shouldn't we be able to perform thisc heck even when the class
+ // type is dependent? Both gcc and edg can handle that.
if (!ClassType->isDependentType()) {
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(
@@ -3079,7 +3134,10 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
Diag(NewFD->getLocation(), diag::err_destructor_name);
return NewFD->setInvalidDecl();
}
+
+ CheckDestructor(Destructor);
}
+
Record->setUserDeclaredDestructor(true);
// C++ [class]p4: A POD-struct is an aggregate class that has [...] no
// user-defined destructor.
@@ -3257,8 +3315,13 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
return;
}
- if (!VDecl->getType()->isArrayType() &&
- RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
+ // A definition must end up with a complete type, which means it must be
+ // complete with the restriction that an array type might be completed by the
+ // initializer; note that later code assumes this restriction.
+ QualType BaseDeclType = VDecl->getType();
+ if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
+ BaseDeclType = Array->getElementType();
+ if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
diag::err_typecheck_decl_incomplete_type)) {
RealDecl->setInvalidDecl();
return;
@@ -3433,6 +3496,16 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
return;
}
+ // An array without size is an incomplete type, and there are no special
+ // rules in C++ to make such a definition acceptable.
+ if (getLangOptions().CPlusPlus && Type->isIncompleteArrayType() &&
+ !Var->hasExternalStorage()) {
+ Diag(Var->getLocation(),
+ diag::err_typecheck_incomplete_array_needs_initializer);
+ Var->setInvalidDecl();
+ return;
+ }
+
// C++ [temp.expl.spec]p15:
// An explicit specialization of a static data member of a template is a
// definition if the declaration includes an initializer; otherwise, it
@@ -3563,7 +3636,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
// template <typename... Args> void f(Args... args) {
// int vals[] = { args };
// }
- const IncompleteArrayType *IAT = T->getAs<IncompleteArrayType>();
+ const IncompleteArrayType *IAT = Context.getAsIncompleteArrayType(T);
Expr *Init = IDecl->getInit();
if (IAT && Init &&
(Init->isTypeDependent() || Init->isValueDependent())) {
@@ -3987,7 +4060,15 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
- computeBaseOrMembersToDestroy(Destructor);
+ MarkBaseAndMemberDestructorsReferenced(Destructor);
+
+ // If any errors have occurred, clear out any temporaries that may have
+ // been leftover. This ensures that these temporaries won't be picked up for
+ // deletion in some later function.
+ if (PP.getDiagnostics().hasErrorOccurred())
+ ExprTemporaries.clear();
+
+ assert(ExprTemporaries.empty() && "Leftover temporaries in function");
return D;
}
@@ -4236,7 +4317,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
bool isStdBadAlloc = false;
bool Invalid = false;
- bool RedeclarationOnly = (TUK != TUK_Reference);
+ RedeclarationKind Redecl = (RedeclarationKind) (TUK != TUK_Reference);
if (Name && SS.isNotEmpty()) {
// We have a nested-name tag ('struct foo::bar').
@@ -4263,15 +4344,13 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DC = computeDeclContext(SS, true);
SearchDC = DC;
// Look-up name inside 'foo::'.
- LookupResult R;
- LookupQualifiedName(R, DC, Name, LookupTagName, RedeclarationOnly);
+ LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl);
+ LookupQualifiedName(R, DC);
- if (R.isAmbiguous()) {
- DiagnoseAmbiguousLookup(R, Name, NameLoc, SS.getRange());
+ if (R.isAmbiguous())
return DeclPtrTy();
- }
- if (R.getKind() == LookupResult::Found)
+ if (R.getResultKind() == LookupResult::Found)
PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl());
// A tag 'foo::bar' must already exist.
@@ -4287,10 +4366,9 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: We're looking into outer scopes here, even when we
// shouldn't be. Doing so can result in ambiguities that we
// shouldn't be diagnosing.
- LookupResult R;
- LookupName(R, S, Name, LookupTagName, RedeclarationOnly);
+ LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl);
+ LookupName(R, S);
if (R.isAmbiguous()) {
- DiagnoseAmbiguousLookup(R, Name, NameLoc);
// FIXME: This is not best way to recover from case like:
//
// struct S s;
@@ -4552,8 +4630,9 @@ CreateNewDecl:
// shall not be declared with the same name as a typedef-name
// that is declared in that scope and refers to a type other
// than the class or enumeration itself.
- LookupResult Lookup;
- LookupName(Lookup, S, Name, LookupOrdinaryName, true);
+ LookupResult Lookup(*this, Name, NameLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ LookupName(Lookup, S);
TypedefDecl *PrevTypedef = 0;
if (NamedDecl *Prev = Lookup.getAsSingleDecl(Context))
PrevTypedef = dyn_cast<TypedefDecl>(Prev);
@@ -4772,7 +4851,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true);
+ NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName,
+ ForRedeclaration);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
@@ -5157,7 +5237,8 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
DInfo, ac, (Expr *)BitfieldWidth);
if (II) {
- NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true);
+ NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName,
+ ForRedeclaration);
if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
&& !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
@@ -5352,21 +5433,25 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
llvm::APSInt EnumVal(32);
QualType EltTy;
- if (Val && !Val->isTypeDependent()) {
- // Make sure to promote the operand type to int.
- UsualUnaryConversions(Val);
- if (Val != val.get()) {
- val.release();
- val = Val;
- }
+ if (Val) {
+ if (Val->isTypeDependent())
+ EltTy = Context.DependentTy;
+ else {
+ // Make sure to promote the operand type to int.
+ UsualUnaryConversions(Val);
+ if (Val != val.get()) {
+ val.release();
+ val = Val;
+ }
- // C99 6.7.2.2p2: Make sure we have an integer constant expression.
- SourceLocation ExpLoc;
- if (!Val->isValueDependent() &&
- VerifyIntegerConstantExpression(Val, &EnumVal)) {
- Val = 0;
- } else {
- EltTy = Val->getType();
+ // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+ SourceLocation ExpLoc;
+ if (!Val->isValueDependent() &&
+ VerifyIntegerConstantExpression(Val, &EnumVal)) {
+ Val = 0;
+ } else {
+ EltTy = Val->getType();
+ }
}
}
@@ -5388,6 +5473,8 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
}
}
+ assert(!EltTy.isNull() && "Enum constant with NULL type");
+
val.release();
return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
Val, EnumVal);
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 18f57da76912..c96ab4681cc5 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -862,7 +862,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
} else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
// We ignore weak import on properties and methods
return;
- } else {
+ } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << 2 /*variable and function*/;
return;
@@ -1008,6 +1008,38 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
+static void HandleCDeclAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // Attribute has no arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // Attribute can be applied only to functions.
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ // cdecl and fastcall attributes are mutually incompatible.
+ if (d->getAttr<FastCallAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "cdecl" << "fastcall";
+ return;
+ }
+
+ // cdecl and stdcall attributes are mutually incompatible.
+ if (d->getAttr<StdCallAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "cdecl" << "stdcall";
+ return;
+ }
+
+ d->addAttr(::new (S.Context) CDeclAttr());
+}
+
+
static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// Attribute has no arguments.
if (Attr.getNumArgs() != 0) {
@@ -1319,7 +1351,14 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: Do we need to bounds check?
unsigned ArgIdx = Idx.getZExtValue() - 1;
- if (HasImplicitThisParam) ArgIdx--;
+ if (HasImplicitThisParam) {
+ if (ArgIdx == 0) {
+ S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ << "a string type" << IdxExpr->getSourceRange();
+ return;
+ }
+ ArgIdx--;
+ }
// make sure the format string is really a string
QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
@@ -1822,6 +1861,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_analyzer_noreturn:
HandleAnalyzerNoReturnAttr (D, Attr, S); break;
case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
+ case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break;
case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break;
case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break;
case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b8977cfa142d..237a869f9084 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -12,15 +12,17 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/DeclSpec.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::equal
@@ -264,9 +266,18 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
ParmVarDecl *NewParam = New->getParamDecl(p);
if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) {
+ // FIXME: If the parameter doesn't have an identifier then the location
+ // points to the '=' which means that the fixit hint won't remove any
+ // extra spaces between the type and the '='.
+ SourceLocation Begin = NewParam->getLocation();
+ if (NewParam->getIdentifier())
+ Begin = PP.getLocForEndOfToken(Begin);
+
Diag(NewParam->getLocation(),
diag::err_param_default_argument_redefinition)
- << NewParam->getDefaultArgRange();
+ << NewParam->getDefaultArgRange()
+ << CodeModificationHint::CreateRemoval(SourceRange(Begin,
+ NewParam->getLocEnd()));
// Look for the function declaration where the default argument was
// actually written, which may be a declaration prior to Old.
@@ -577,7 +588,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
for (unsigned idx = 0; idx < NumBases; ++idx) {
QualType NewBaseType
= Context.getCanonicalType(Bases[idx]->getType());
- NewBaseType = NewBaseType.getUnqualifiedType();
+ NewBaseType = NewBaseType.getLocalUnqualifiedType();
if (KnownBaseTypes[NewBaseType]) {
// C++ [class.mi]p3:
@@ -688,6 +699,8 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
(void)DerivationOkay;
if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
+ if (InaccessibleBaseID == 0)
+ return false;
// Check that the base class can be accessed.
return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc,
Name);
@@ -718,9 +731,11 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
- SourceLocation Loc, SourceRange Range) {
+ SourceLocation Loc, SourceRange Range,
+ bool IgnoreAccess) {
return CheckDerivedToBaseConversion(Derived, Base,
- diag::err_conv_to_inaccessible_base,
+ IgnoreAccess ? 0 :
+ diag::err_conv_to_inaccessible_base,
diag::err_ambiguous_derived_to_base_conv,
Loc, Range, DeclarationName());
}
@@ -1018,6 +1033,10 @@ Sema::MemInitResult
Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc,
SourceLocation RParenLoc) {
+ // FIXME: CXXBaseOrMemberInitializer should only contain a single
+ // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
+ ExprTemporaries.clear();
+
// Diagnose value-uses of fields to initialize themselves, e.g.
// foo(foo)
// where foo is not also a parameter to the constructor.
@@ -1088,6 +1107,11 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
return true;
Args[0] = NewExp;
}
+
+ // FIXME: CXXBaseOrMemberInitializer should only contain a single
+ // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
+ ExprTemporaries.clear();
+
// FIXME: Perform direct initialization of the member.
return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args,
NumArgs, C, IdLoc, RParenLoc);
@@ -1117,8 +1141,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args,
const CXXBaseSpecifier *DirectBaseSpec = 0;
for (CXXRecordDecl::base_class_const_iterator Base =
ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) {
- if (Context.getCanonicalType(BaseType).getUnqualifiedType() ==
- Context.getCanonicalType(Base->getType()).getUnqualifiedType()) {
+ if (Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
// We found a direct base of this type. That's what we're
// initializing.
DirectBaseSpec = &*Base;
@@ -1166,7 +1189,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args,
CXXConstructorDecl *C = 0;
if (!BaseType->isDependentType() && !HasDependentArg) {
DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(BaseType));
+ Context.getCanonicalType(BaseType).getUnqualifiedType());
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
C = PerformInitializationByConstructor(BaseType,
@@ -1182,22 +1205,26 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args,
}
}
+ // FIXME: CXXBaseOrMemberInitializer should only contain a single
+ // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
+ ExprTemporaries.clear();
+
return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args,
NumArgs, C, IdLoc, RParenLoc);
}
-void
+bool
Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
- llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
- llvm::SmallVectorImpl<FieldDecl *>&Fields) {
+ bool IsImplicitConstructor) {
// We need to build the initializer AST according to order of construction
// and not what user specified in the Initializers list.
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext());
llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
bool HasDependentBaseInit = false;
+ bool HadError = false;
for (unsigned i = 0; i < NumInitializers; i++) {
CXXBaseOrMemberInitializer *Member = Initializers[i];
@@ -1239,13 +1266,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
if (VBase->getType()->isDependentType())
continue;
- if (CXXBaseOrMemberInitializer *Value =
- AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
- CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
- if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
- MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
+ if (CXXBaseOrMemberInitializer *Value
+ = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
AllToInit.push_back(Value);
}
else {
@@ -1254,7 +1276,12 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null");
CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
if (!Ctor) {
- Bases.push_back(VBase);
+ Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
+ << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+ << 0 << VBase->getType();
+ Diag(VBaseDecl->getLocation(), diag::note_previous_class_decl)
+ << Context.getTagDeclType(VBaseDecl);
+ HadError = true;
continue;
}
@@ -1265,6 +1292,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+ // FIXME: CXXBaseOrMemberInitializer should only contain a single
+ // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
+ ExprTemporaries.clear();
CXXBaseOrMemberInitializer *Member =
new (Context) CXXBaseOrMemberInitializer(VBase->getType(),
CtorArgs.takeAs<Expr>(),
@@ -1284,13 +1314,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
// Skip dependent types.
if (Base->getType()->isDependentType())
continue;
- if (CXXBaseOrMemberInitializer *Value =
- AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
- CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
- if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
- MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
+ if (CXXBaseOrMemberInitializer *Value
+ = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
AllToInit.push_back(Value);
}
else {
@@ -1299,7 +1324,12 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
if (!Ctor) {
- Bases.push_back(Base);
+ Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
+ << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+ << 0 << Base->getType();
+ Diag(BaseDecl->getLocation(), diag::note_previous_class_decl)
+ << Context.getTagDeclType(BaseDecl);
+ HadError = true;
continue;
}
@@ -1310,6 +1340,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+ // FIXME: CXXBaseOrMemberInitializer should only contain a single
+ // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
+ ExprTemporaries.clear();
CXXBaseOrMemberInitializer *Member =
new (Context) CXXBaseOrMemberInitializer(Base->getType(),
CtorArgs.takeAs<Expr>(),
@@ -1328,7 +1361,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
if (const RecordType *FieldClassType =
Field->getType()->getAs<RecordType>()) {
CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
EA = FieldClassDecl->field_end(); FA != EA; FA++) {
if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) {
@@ -1345,37 +1378,49 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
continue;
}
if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*Field)) {
- QualType FT = (*Field)->getType();
- if (const RecordType* RT = FT->getAs<RecordType>()) {
- CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl());
- assert(FieldRecDecl && "SetBaseOrMemberInitializers - BaseDecl null");
- if (CXXConstructorDecl *Ctor =
- FieldRecDecl->getDefaultConstructor(Context))
- MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
- }
AllToInit.push_back(Value);
continue;
}
- if ((*Field)->getType()->isDependentType()) {
- Fields.push_back(*Field);
+ if ((*Field)->getType()->isDependentType())
continue;
- }
QualType FT = Context.getBaseElementType((*Field)->getType());
if (const RecordType* RT = FT->getAs<RecordType>()) {
CXXConstructorDecl *Ctor =
cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
if (!Ctor) {
- Fields.push_back(*Field);
+ Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
+ << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+ << 1 << (*Field)->getDeclName();
+ Diag(Field->getLocation(), diag::note_field_decl);
+ Diag(RT->getDecl()->getLocation(), diag::note_previous_class_decl)
+ << Context.getTagDeclType(RT->getDecl());
+ HadError = true;
continue;
}
-
+
+ if (FT.isConstQualified() && Ctor->isTrivial()) {
+ Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
+ << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+ << 1 << (*Field)->getDeclName();
+ Diag((*Field)->getLocation(), diag::note_declared_at);
+ HadError = true;
+ }
+
+ // Don't create initializers for trivial constructors, since they don't
+ // actually need to be run.
+ if (Ctor->isTrivial())
+ continue;
+
ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
Constructor->getLocation(), CtorArgs))
continue;
+ // FIXME: CXXBaseOrMemberInitializer should only contain a single
+ // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
+ ExprTemporaries.clear();
CXXBaseOrMemberInitializer *Member =
new (Context) CXXBaseOrMemberInitializer(*Field,CtorArgs.takeAs<Expr>(),
CtorArgs.size(), Ctor,
@@ -1383,23 +1428,21 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
SourceLocation());
AllToInit.push_back(Member);
- if (Ctor)
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
- if (FT.isConstQualified() && (!Ctor || Ctor->isTrivial())) {
- Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
- << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName();
- Diag((*Field)->getLocation(), diag::note_declared_at);
- }
+ MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
}
else if (FT->isReferenceType()) {
Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
- << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getDeclName();
+ << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+ << 0 << (*Field)->getDeclName();
Diag((*Field)->getLocation(), diag::note_declared_at);
+ HadError = true;
}
else if (FT.isConstQualified()) {
Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
- << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName();
+ << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+ << 1 << (*Field)->getDeclName();
Diag((*Field)->getLocation(), diag::note_declared_at);
+ HadError = true;
}
}
@@ -1413,29 +1456,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
for (unsigned Idx = 0; Idx < NumInitializers; ++Idx)
baseOrMemberInitializers[Idx] = AllToInit[Idx];
}
-}
-
-void
-Sema::BuildBaseOrMemberInitializers(ASTContext &C,
- CXXConstructorDecl *Constructor,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers
- ) {
- llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
- llvm::SmallVector<FieldDecl *, 4> Members;
- SetBaseOrMemberInitializers(Constructor,
- Initializers, NumInitializers, Bases, Members);
- for (unsigned int i = 0; i < Bases.size(); i++) {
- if (!Bases[i]->getType()->isDependentType())
- Diag(Bases[i]->getSourceRange().getBegin(),
- diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
- }
- for (unsigned int i = 0; i < Members.size(); i++) {
- if (!Members[i]->getType()->isDependentType())
- Diag(Members[i]->getLocation(), diag::err_missing_default_constructor)
- << 1 << Members[i]->getType();
- }
+ return HadError;
}
static void *GetKeyForTopLevelField(FieldDecl *Field) {
@@ -1462,7 +1484,7 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member,
if (Member->isMemberInitializer()) {
FieldDecl *Field = Member->getMember();
- // After BuildBaseOrMemberInitializers call, Field is the anonymous union
+ // After SetBaseOrMemberInitializers call, Field is the anonymous union
// data member of the class. Data member used in the initializer list is
// in AnonUnionMember field.
if (MemberMaybeAnon && Field->isAnonymousStructOrUnion())
@@ -1527,9 +1549,9 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
return;
}
- BuildBaseOrMemberInitializers(Context, Constructor,
+ SetBaseOrMemberInitializers(Constructor,
reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
- NumMemInits);
+ NumMemInits, false);
if (Constructor->isDependentContext())
return;
@@ -1612,77 +1634,63 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
}
void
-Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) {
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
- llvm::SmallVector<uintptr_t, 32> AllToDestruct;
+Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) {
+ // Ignore dependent destructors.
+ if (Destructor->isDependentContext())
+ return;
+
+ CXXRecordDecl *ClassDecl = Destructor->getParent();
- for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
- if (VBase->getType()->isDependentType())
+ // Non-static data members.
+ for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); I != E; ++I) {
+ FieldDecl *Field = *I;
+
+ QualType FieldType = Context.getBaseElementType(Field->getType());
+
+ const RecordType* RT = FieldType->getAs<RecordType>();
+ if (!RT)
continue;
- // Skip over virtual bases which have trivial destructors.
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- if (BaseClassDecl->hasTrivialDestructor())
+
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (FieldClassDecl->hasTrivialDestructor())
continue;
- if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
- MarkDeclarationReferenced(Destructor->getLocation(),
- const_cast<CXXDestructorDecl*>(Dtor));
- uintptr_t Member =
- reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr())
- | CXXDestructorDecl::VBASE;
- AllToDestruct.push_back(Member);
+ const CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context);
+ MarkDeclarationReferenced(Destructor->getLocation(),
+ const_cast<CXXDestructorDecl*>(Dtor));
}
- for (CXXRecordDecl::base_class_iterator Base =
- ClassDecl->bases_begin(),
+
+ // Bases.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
E = ClassDecl->bases_end(); Base != E; ++Base) {
+ // Ignore virtual bases.
if (Base->isVirtual())
continue;
- if (Base->getType()->isDependentType())
- continue;
- // Skip over virtual bases which have trivial destructors.
+
+ // Ignore trivial destructors.
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (BaseClassDecl->hasTrivialDestructor())
continue;
- if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
- MarkDeclarationReferenced(Destructor->getLocation(),
- const_cast<CXXDestructorDecl*>(Dtor));
- uintptr_t Member =
- reinterpret_cast<uintptr_t>(Base->getType().getTypePtr())
- | CXXDestructorDecl::DRCTNONVBASE;
- AllToDestruct.push_back(Member);
- }
-
- // non-static data members.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); Field != E; ++Field) {
- QualType FieldType = Context.getBaseElementType((*Field)->getType());
-
- if (const RecordType* RT = FieldType->getAs<RecordType>()) {
- // Skip over virtual bases which have trivial destructors.
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (FieldClassDecl->hasTrivialDestructor())
- continue;
- if (const CXXDestructorDecl *Dtor =
- FieldClassDecl->getDestructor(Context))
- MarkDeclarationReferenced(Destructor->getLocation(),
- const_cast<CXXDestructorDecl*>(Dtor));
- uintptr_t Member = reinterpret_cast<uintptr_t>(*Field);
- AllToDestruct.push_back(Member);
- }
+
+ const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+ MarkDeclarationReferenced(Destructor->getLocation(),
+ const_cast<CXXDestructorDecl*>(Dtor));
}
-
- unsigned NumDestructions = AllToDestruct.size();
- if (NumDestructions > 0) {
- Destructor->setNumBaseOrMemberDestructions(NumDestructions);
- uintptr_t *BaseOrMemberDestructions =
- new (Context) uintptr_t [NumDestructions];
- // Insert in reverse order.
- for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx)
- BaseOrMemberDestructions[i++] = AllToDestruct[Idx];
- Destructor->setBaseOrMemberDestructions(BaseOrMemberDestructions);
+
+ // Virtual bases.
+ for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+ E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+ // Ignore trivial destructors.
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+
+ const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+ MarkDeclarationReferenced(Destructor->getLocation(),
+ const_cast<CXXDestructorDecl*>(Dtor));
}
}
@@ -1694,9 +1702,7 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
- BuildBaseOrMemberInitializers(Context,
- Constructor,
- (CXXBaseOrMemberInitializer **)0, 0);
+ SetBaseOrMemberInitializers(Constructor, 0, 0, false);
}
namespace {
@@ -1931,7 +1937,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
}
if (RD->isAbstract())
- AbstractClassUsageDiagnoser(*this, RD);
+ (void)AbstractClassUsageDiagnoser(*this, RD);
if (!RD->isDependentType() && !RD->isInvalidDecl())
AddImplicitlyDeclaredMembersToClass(RD);
@@ -2334,13 +2340,18 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
if (!Constructor->isInvalidDecl() &&
((Constructor->getNumParams() == 1) ||
(Constructor->getNumParams() > 1 &&
- Constructor->getParamDecl(1)->hasDefaultArg()))) {
+ Constructor->getParamDecl(1)->hasDefaultArg())) &&
+ Constructor->getTemplateSpecializationKind()
+ != TSK_ImplicitInstantiation) {
QualType ParamType = Constructor->getParamDecl(0)->getType();
QualType ClassTy = Context.getTagDeclType(ClassDecl);
if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
Diag(ParamLoc, diag::err_constructor_byvalue_arg)
<< CodeModificationHint::CreateInsertion(ParamLoc, " const &");
+
+ // FIXME: Rather that making the constructor invalid, we should endeavor
+ // to fix the type.
Constructor->setInvalidDecl();
}
}
@@ -2349,6 +2360,28 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
ClassDecl->addedConstructor(Context, Constructor);
}
+/// CheckDestructor - Checks a fully-formed destructor for
+/// well-formedness, issuing any diagnostics required.
+void Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
+ CXXRecordDecl *RD = Destructor->getParent();
+
+ if (Destructor->isVirtual()) {
+ SourceLocation Loc;
+
+ if (!Destructor->isImplicit())
+ Loc = Destructor->getLocation();
+ else
+ Loc = RD->getLocation();
+
+ // If we have a virtual destructor, look up the deallocation function
+ FunctionDecl *OperatorDelete = 0;
+ DeclarationName Name =
+ Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+ if (!FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
+ Destructor->setOperatorDelete(OperatorDelete);
+ }
+}
+
static inline bool
FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
@@ -2606,7 +2639,8 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// in that declarative region, it is treated as an original-namespace-name.
NamedDecl *PrevDecl
- = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName, true);
+ = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName,
+ ForRedeclaration);
if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
// This is an extended namespace definition.
@@ -2714,14 +2748,14 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
UsingDirectiveDecl *UDir = 0;
// Lookup namespace name.
- LookupResult R;
- LookupParsedName(R, S, &SS, NamespcName, LookupNamespaceName, false);
- if (R.isAmbiguous()) {
- DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc);
+ LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
+ LookupParsedName(R, S, &SS);
+ if (R.isAmbiguous())
return DeclPtrTy();
- }
+
if (!R.empty()) {
NamedDecl *NS = R.getFoundDecl();
+ // FIXME: Namespace aliases!
assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
// C++ [namespace.udir]p1:
// A using-directive specifies that the names in the nominated
@@ -2776,7 +2810,8 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName) {
+ bool IsTypeName,
+ SourceLocation TypenameLoc) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
switch (Name.getKind()) {
@@ -2802,9 +2837,11 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
}
DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
- NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS,
+ NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
Name.getSourceRange().getBegin(),
- TargetName, AttrList, IsTypeName);
+ TargetName, AttrList,
+ /* IsInstantiation */ false,
+ IsTypeName, TypenameLoc);
if (UD) {
PushOnScopeChains(UD, S);
UD->setAccess(AS);
@@ -2813,12 +2850,46 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
return DeclPtrTy::make(UD);
}
-NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
+/// Builds a shadow declaration corresponding to a 'using' declaration.
+static UsingShadowDecl *BuildUsingShadowDecl(Sema &SemaRef, Scope *S,
+ AccessSpecifier AS,
+ UsingDecl *UD, NamedDecl *Orig) {
+ // FIXME: diagnose hiding, collisions
+
+ // If we resolved to another shadow declaration, just coalesce them.
+ if (isa<UsingShadowDecl>(Orig)) {
+ Orig = cast<UsingShadowDecl>(Orig)->getTargetDecl();
+ assert(!isa<UsingShadowDecl>(Orig) && "nested shadow declaration");
+ }
+
+ UsingShadowDecl *Shadow
+ = UsingShadowDecl::Create(SemaRef.Context, SemaRef.CurContext,
+ UD->getLocation(), UD, Orig);
+ UD->addShadowDecl(Shadow);
+
+ if (S)
+ SemaRef.PushOnScopeChains(Shadow, S);
+ else
+ SemaRef.CurContext->addDecl(Shadow);
+ Shadow->setAccess(AS);
+
+ return Shadow;
+}
+
+/// Builds a using declaration.
+///
+/// \param IsInstantiation - Whether this call arises from an
+/// instantiation of an unresolved using declaration. We treat
+/// the lookup differently for these declarations.
+NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
DeclarationName Name,
AttributeList *AttrList,
- bool IsTypeName) {
+ bool IsInstantiation,
+ bool IsTypeName,
+ SourceLocation TypenameLoc) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(IdentLoc.isValid() && "Invalid TargetName location.");
@@ -2833,14 +2904,20 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
NestedNameSpecifier *NNS =
static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- if (isUnknownSpecialization(SS)) {
- return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc,
- SS.getRange(), NNS,
- IdentLoc, Name, IsTypeName);
+ DeclContext *LookupContext = computeDeclContext(SS);
+ if (!LookupContext) {
+ if (IsTypeName) {
+ return UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+ UsingLoc, TypenameLoc,
+ SS.getRange(), NNS,
+ IdentLoc, Name);
+ } else {
+ return UnresolvedUsingValueDecl::Create(Context, CurContext,
+ UsingLoc, SS.getRange(), NNS,
+ IdentLoc, Name);
+ }
}
- DeclContext *LookupContext = 0;
-
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
// C++0x N2914 [namespace.udecl]p3:
// A using-declaration used as a member-declaration shall refer to a member
@@ -2848,37 +2925,36 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
// anonymous union that is a member of a base class of the class being
// defined, or shall refer to an enumerator for an enumeration type that is
// a member of a base class of the class being defined.
- const Type *Ty = NNS->getAsType();
- if (!Ty || !IsDerivedFrom(Context.getTagDeclType(RD), QualType(Ty, 0))) {
+
+ CXXRecordDecl *LookupRD = dyn_cast<CXXRecordDecl>(LookupContext);
+ if (!LookupRD || !RD->isDerivedFrom(LookupRD)) {
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_a_base_class)
<< NNS << RD->getDeclName();
return 0;
}
-
- QualType BaseTy = Context.getCanonicalType(QualType(Ty, 0));
- LookupContext = BaseTy->getAs<RecordType>()->getDecl();
} else {
// C++0x N2914 [namespace.udecl]p8:
// A using-declaration for a class member shall be a member-declaration.
- if (NNS->getKind() == NestedNameSpecifier::TypeSpec) {
+ if (isa<CXXRecordDecl>(LookupContext)) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
return 0;
}
-
- // C++0x N2914 [namespace.udecl]p9:
- // In a using-declaration, a prefix :: refers to the global namespace.
- if (NNS->getKind() == NestedNameSpecifier::Global)
- LookupContext = Context.getTranslationUnitDecl();
- else
- LookupContext = NNS->getAsNamespace();
}
+ // Look up the target name. Unlike most lookups, we do not want to
+ // hide tag declarations: tag names are visible through the using
+ // declaration even if hidden by ordinary names.
+ LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName);
- // Lookup target name.
- LookupResult R;
- LookupQualifiedName(R, LookupContext, Name, LookupOrdinaryName);
+ // We don't hide tags behind ordinary decls if we're in a
+ // non-dependent context, but in a dependent context, this is
+ // important for the stability of two-phase lookup.
+ if (!IsInstantiation)
+ R.setHideTags(false);
+
+ LookupQualifiedName(R, LookupContext);
if (R.empty()) {
Diag(IdentLoc, diag::err_no_member)
@@ -2886,24 +2962,49 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
return 0;
}
- // FIXME: handle ambiguity?
- NamedDecl *ND = R.getAsSingleDecl(Context);
-
- if (IsTypeName && !isa<TypeDecl>(ND)) {
- Diag(IdentLoc, diag::err_using_typename_non_type);
+ if (R.isAmbiguous())
return 0;
+
+ if (IsTypeName) {
+ // If we asked for a typename and got a non-type decl, error out.
+ if (R.getResultKind() != LookupResult::Found
+ || !isa<TypeDecl>(R.getFoundDecl())) {
+ Diag(IdentLoc, diag::err_using_typename_non_type);
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ Diag((*I)->getUnderlyingDecl()->getLocation(),
+ diag::note_using_decl_target);
+ return 0;
+ }
+ } else {
+ // If we asked for a non-typename and we got a type, error out,
+ // but only if this is an instantiation of an unresolved using
+ // decl. Otherwise just silently find the type name.
+ if (IsInstantiation &&
+ R.getResultKind() == LookupResult::Found &&
+ isa<TypeDecl>(R.getFoundDecl())) {
+ Diag(IdentLoc, diag::err_using_dependent_value_is_type);
+ Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
+ return 0;
+ }
}
// C++0x N2914 [namespace.udecl]p6:
// A using-declaration shall not name a namespace.
- if (isa<NamespaceDecl>(ND)) {
+ if (R.getResultKind() == LookupResult::Found
+ && isa<NamespaceDecl>(R.getFoundDecl())) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
<< SS.getRange();
return 0;
}
- return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
- ND->getLocation(), UsingLoc, ND, NNS, IsTypeName);
+ UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc,
+ SS.getRange(), UsingLoc, NNS, Name,
+ IsTypeName);
+
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ BuildUsingShadowDecl(*this, S, AS, UD, *I);
+
+ return UD;
}
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
@@ -2923,12 +3024,12 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
IdentifierInfo *Ident) {
// Lookup the namespace name.
- LookupResult R;
- LookupParsedName(R, S, &SS, Ident, LookupNamespaceName, false);
+ LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
+ LookupParsedName(R, S, &SS);
// Check if we have a previous declaration with the same name.
if (NamedDecl *PrevDecl
- = LookupSingleName(S, Alias, LookupOrdinaryName, true)) {
+ = LookupSingleName(S, Alias, LookupOrdinaryName, ForRedeclaration)) {
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
// We already have an alias with the same name that points to the same
// namespace, so don't create a new one.
@@ -2944,10 +3045,8 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
return DeclPtrTy();
}
- if (R.isAmbiguous()) {
- DiagnoseAmbiguousLookup(R, Ident, IdentLoc);
+ if (R.isAmbiguous())
return DeclPtrTy();
- }
if (R.empty()) {
Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
@@ -2973,76 +3072,22 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(Constructor->getDeclContext());
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
- // Before the implicitly-declared default constructor for a class is
- // implicitly defined, all the implicitly-declared default constructors
- // for its base class and its non-static data members shall have been
- // implicitly defined.
- bool err = false;
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- if (!BaseClassDecl->hasTrivialConstructor()) {
- if (CXXConstructorDecl *BaseCtor =
- BaseClassDecl->getDefaultConstructor(Context))
- MarkDeclarationReferenced(CurrentLocation, BaseCtor);
- else {
- Diag(CurrentLocation, diag::err_defining_default_ctor)
- << Context.getTagDeclType(ClassDecl) << 0
- << Context.getTagDeclType(BaseClassDecl);
- Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl)
- << Context.getTagDeclType(BaseClassDecl);
- err = true;
- }
- }
- }
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); Field != E; ++Field) {
- QualType FieldType = Context.getCanonicalType((*Field)->getType());
- if (const ArrayType *Array = Context.getAsArrayType(FieldType))
- FieldType = Array->getElementType();
- if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
- if (!FieldClassDecl->hasTrivialConstructor()) {
- if (CXXConstructorDecl *FieldCtor =
- FieldClassDecl->getDefaultConstructor(Context))
- MarkDeclarationReferenced(CurrentLocation, FieldCtor);
- else {
- Diag(CurrentLocation, diag::err_defining_default_ctor)
- << Context.getTagDeclType(ClassDecl) << 1 <<
- Context.getTagDeclType(FieldClassDecl);
- Diag((*Field)->getLocation(), diag::note_field_decl);
- Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl)
- << Context.getTagDeclType(FieldClassDecl);
- err = true;
- }
- }
- } else if (FieldType->isReferenceType()) {
- Diag(CurrentLocation, diag::err_unintialized_member)
- << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
- Diag((*Field)->getLocation(), diag::note_declared_at);
- err = true;
- } else if (FieldType.isConstQualified()) {
- Diag(CurrentLocation, diag::err_unintialized_member)
- << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
- Diag((*Field)->getLocation(), diag::note_declared_at);
- err = true;
- }
- }
- if (!err)
- Constructor->setUsed();
- else
+
+ if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) {
+ Diag(CurrentLocation, diag::note_ctor_synthesized_at)
+ << Context.getTagDeclType(ClassDecl);
Constructor->setInvalidDecl();
+ } else {
+ Constructor->setUsed();
+ }
+ return;
}
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
CXXDestructorDecl *Destructor) {
assert((Destructor->isImplicit() && !Destructor->isUsed()) &&
"DefineImplicitDestructor - call it for implicit default dtor");
-
- CXXRecordDecl *ClassDecl
- = cast<CXXRecordDecl>(Destructor->getDeclContext());
+ CXXRecordDecl *ClassDecl = Destructor->getParent();
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
// C++ [class.dtor] p5
// Before the implicitly-declared default destructor for a class is
@@ -3399,6 +3444,107 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
/*DirectInit=*/true);
}
+/// \brief Add the applicable constructor candidates for an initialization
+/// by constructor.
+static void AddConstructorInitializationCandidates(Sema &SemaRef,
+ QualType ClassType,
+ Expr **Args,
+ unsigned NumArgs,
+ Sema::InitializationKind Kind,
+ OverloadCandidateSet &CandidateSet) {
+ // C++ [dcl.init]p14:
+ // If the initialization is direct-initialization, or if it is
+ // copy-initialization where the cv-unqualified version of the
+ // source type is the same class as, or a derived class of, the
+ // class of the destination, constructors are considered. The
+ // applicable constructors are enumerated (13.3.1.3), and the
+ // best one is chosen through overload resolution (13.3). The
+ // constructor so selected is called to initialize the object,
+ // with the initializer expression(s) as its argument(s). If no
+ // constructor applies, or the overload resolution is ambiguous,
+ // the initialization is ill-formed.
+ const RecordType *ClassRec = ClassType->getAs<RecordType>();
+ assert(ClassRec && "Can only initialize a class type here");
+
+ // FIXME: When we decide not to synthesize the implicitly-declared
+ // constructors, we'll need to make them appear here.
+
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
+ DeclarationName ConstructorName
+ = SemaRef.Context.DeclarationNames.getCXXConstructorName(
+ SemaRef.Context.getCanonicalType(ClassType).getUnqualifiedType());
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con);
+ if (ConstructorTmpl)
+ Constructor
+ = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
+ else
+ Constructor = cast<CXXConstructorDecl>(*Con);
+
+ if ((Kind == Sema::IK_Direct) ||
+ (Kind == Sema::IK_Copy &&
+ Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) ||
+ (Kind == Sema::IK_Default && Constructor->isDefaultConstructor())) {
+ if (ConstructorTmpl)
+ SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0,
+ Args, NumArgs, CandidateSet);
+ else
+ SemaRef.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
+ }
+ }
+}
+
+/// \brief Attempt to perform initialization by constructor
+/// (C++ [dcl.init]p14), which may occur as part of direct-initialization or
+/// copy-initialization.
+///
+/// This routine determines whether initialization by constructor is possible,
+/// but it does not emit any diagnostics in the case where the initialization
+/// is ill-formed.
+///
+/// \param ClassType the type of the object being initialized, which must have
+/// class type.
+///
+/// \param Args the arguments provided to initialize the object
+///
+/// \param NumArgs the number of arguments provided to initialize the object
+///
+/// \param Kind the type of initialization being performed
+///
+/// \returns the constructor used to initialize the object, if successful.
+/// Otherwise, emits a diagnostic and returns NULL.
+CXXConstructorDecl *
+Sema::TryInitializationByConstructor(QualType ClassType,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation Loc,
+ InitializationKind Kind) {
+ // Build the overload candidate set
+ OverloadCandidateSet CandidateSet;
+ AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind,
+ CandidateSet);
+
+ // Determine whether we found a constructor we can use.
+ OverloadCandidateSet::iterator Best;
+ switch (BestViableFunction(CandidateSet, Loc, Best)) {
+ case OR_Success:
+ case OR_Deleted:
+ // We found a constructor. Return it.
+ return cast<CXXConstructorDecl>(Best->Function);
+
+ case OR_No_Viable_Function:
+ case OR_Ambiguous:
+ // Overload resolution failed. Return nothing.
+ return 0;
+ }
+
+ // Silence GCC warning
+ return 0;
+}
+
/// \brief Perform initialization by constructor (C++ [dcl.init]p14), which
/// may occur as part of direct-initialization or copy-initialization.
///
@@ -3428,55 +3574,13 @@ Sema::PerformInitializationByConstructor(QualType ClassType,
DeclarationName InitEntity,
InitializationKind Kind,
ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) {
- const RecordType *ClassRec = ClassType->getAs<RecordType>();
- assert(ClassRec && "Can only initialize a class type here");
+
+ // Build the overload candidate set
Expr **Args = (Expr **)ArgsPtr.get();
unsigned NumArgs = ArgsPtr.size();
-
- // C++ [dcl.init]p14:
- // If the initialization is direct-initialization, or if it is
- // copy-initialization where the cv-unqualified version of the
- // source type is the same class as, or a derived class of, the
- // class of the destination, constructors are considered. The
- // applicable constructors are enumerated (13.3.1.3), and the
- // best one is chosen through overload resolution (13.3). The
- // constructor so selected is called to initialize the object,
- // with the initializer expression(s) as its argument(s). If no
- // constructor applies, or the overload resolution is ambiguous,
- // the initialization is ill-formed.
- const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
OverloadCandidateSet CandidateSet;
-
- // Add constructors to the overload set.
- DeclarationName ConstructorName
- = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(ClassType.getUnqualifiedType()));
- DeclContext::lookup_const_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
- Con != ConEnd; ++Con) {
- // Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
- FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con);
- if (ConstructorTmpl)
- Constructor
- = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
- else
- Constructor = cast<CXXConstructorDecl>(*Con);
-
- if ((Kind == IK_Direct) ||
- (Kind == IK_Copy &&
- Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) ||
- (Kind == IK_Default && Constructor->isDefaultConstructor())) {
- if (ConstructorTmpl)
- AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0,
- Args, NumArgs, CandidateSet);
- else
- AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
- }
- }
-
- // FIXME: When we decide not to synthesize the implicitly-declared
- // constructors, we'll need to make them appear here.
+ AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind,
+ CandidateSet);
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, Loc, Best)) {
@@ -3613,8 +3717,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType T1 = Context.getCanonicalType(OrigT1);
QualType T2 = Context.getCanonicalType(OrigT2);
- QualType UnqualT1 = T1.getUnqualifiedType();
- QualType UnqualT2 = T2.getUnqualifiedType();
+ QualType UnqualT1 = T1.getLocalUnqualifiedType();
+ QualType UnqualT2 = T2.getLocalUnqualifiedType();
// C++ [dcl.init.ref]p4:
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
@@ -3663,12 +3767,15 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
/// When @p AllowExplicit, we also permit explicit user-defined
/// conversion functions.
/// When @p ForceRValue, we unconditionally treat the initializer as an rvalue.
+/// When @p IgnoreBaseAccess, we don't do access control on to-base conversion.
+/// This is used when this is called from a C-style cast.
bool
Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
SourceLocation DeclLoc,
bool SuppressUserConversions,
bool AllowExplicit, bool ForceRValue,
- ImplicitConversionSequence *ICS) {
+ ImplicitConversionSequence *ICS,
+ bool IgnoreBaseAccess) {
assert(DeclType->isReferenceType() && "Reference init needs a reference");
QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType();
@@ -3827,6 +3934,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
ICS->UserDefined.Before = Best->Conversions[0].Standard;
ICS->UserDefined.After = Best->FinalConversion;
ICS->UserDefined.ConversionFunction = Best->Function;
+ ICS->UserDefined.EllipsisConversion = false;
assert(ICS->UserDefined.After.ReferenceBinding &&
ICS->UserDefined.After.DirectBinding &&
"Expected a direct reference binding!");
@@ -3882,7 +3990,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// actually happens.
if (DerivedToBase)
return CheckDerivedToBaseConversion(T2, T1, DeclLoc,
- Init->getSourceRange());
+ Init->getSourceRange(),
+ IgnoreBaseAccess);
else
return false;
}
@@ -4051,9 +4160,28 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
// found in the rest of this subclause do not apply to them unless
// explicitly stated in 3.7.3.
// FIXME: Write a separate routine for checking this. For now, just allow it.
- if (Op == OO_New || Op == OO_Array_New ||
- Op == OO_Delete || Op == OO_Array_Delete)
+ if (Op == OO_Delete || Op == OO_Array_Delete)
return false;
+
+ if (Op == OO_New || Op == OO_Array_New) {
+ bool ret = false;
+ if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) {
+ QualType SizeTy = Context.getCanonicalType(Context.getSizeType());
+ QualType T = Context.getCanonicalType((*Param)->getType());
+ if (!T->isDependentType() && SizeTy != T) {
+ Diag(FnDecl->getLocation(),
+ diag::err_operator_new_param_type) << FnDecl->getDeclName()
+ << SizeTy;
+ ret = true;
+ }
+ }
+ QualType ResultTy = Context.getCanonicalType(FnDecl->getResultType());
+ if (!ResultTy->isDependentType() && ResultTy != Context.VoidPtrTy)
+ return Diag(FnDecl->getLocation(),
+ diag::err_operator_new_result_type) << FnDecl->getDeclName()
+ << static_cast<QualType>(Context.VoidPtrTy);
+ return ret;
+ }
// C++ [over.oper]p6:
// An operator function shall either be a non-static member
@@ -4182,7 +4310,6 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
assert(isa<CXXMethodDecl>(FnDecl) &&
"Overloaded = not member, but not filtered.");
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
- Method->setCopyAssignment(true);
Method->getParent()->addedAssignmentOperator(Context, Method);
}
@@ -4549,8 +4676,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// FIXME: handle dependent contexts
if (!DC) return DeclPtrTy();
- LookupResult R;
- LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true);
+ LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration);
+ LookupQualifiedName(R, DC);
PrevDecl = R.getAsSingleDecl(Context);
// If searching in that context implicitly found a declaration in
@@ -4584,8 +4711,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
while (DC->isRecord())
DC = DC->getParent();
- LookupResult R;
- LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true);
+ LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration);
+ LookupQualifiedName(R, DC);
PrevDecl = R.getAsSingleDecl(Context);
// TODO: decide what we think about using declarations.
@@ -4697,7 +4824,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
QualType COldTy = Context.getCanonicalType(OldTy);
if (CNewTy == COldTy &&
- CNewTy.getCVRQualifiers() == COldTy.getCVRQualifiers())
+ CNewTy.getLocalCVRQualifiers() == COldTy.getLocalCVRQualifiers())
return false;
// Check if the return types are covariant
@@ -4726,7 +4853,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return true;
}
- if (NewClassTy.getUnqualifiedType() != OldClassTy.getUnqualifiedType()) {
+ if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
// Check if the new class derives from the old class.
if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
Diag(New->getLocation(),
@@ -4748,7 +4875,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
}
// The qualifiers of the return types must be the same.
- if (CNewTy.getCVRQualifiers() != COldTy.getCVRQualifiers()) {
+ if (CNewTy.getLocalCVRQualifiers() != COldTy.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 93f8d0dc37c1..0c5569caff00 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -112,6 +112,14 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl->setLocation(AtInterfaceLoc);
IDecl->setForwardDecl(false);
IDecl->setClassLoc(ClassLoc);
+
+ // Since this ObjCInterfaceDecl was created by a forward declaration,
+ // we now add it to the DeclContext since it wasn't added before
+ // (see ActOnForwardClassDeclaration).
+ CurContext->addDecl(IDecl);
+
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
}
} else {
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
@@ -1113,10 +1121,46 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
assert(false && "invalid ObjCContainerDecl type.");
}
+void
+Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl) {
+ // Rules apply in non-GC mode only
+ if (getLangOptions().getGCMode() != LangOptions::NonGC)
+ return;
+ for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
+ E = IDecl->prop_end();
+ I != E; ++I) {
+ ObjCPropertyDecl *Property = (*I);
+ unsigned Attributes = Property->getPropertyAttributes();
+ // We only care about readwrite atomic property.
+ if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
+ !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
+ continue;
+ if (const ObjCPropertyImplDecl *PIDecl
+ = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
+ if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+ continue;
+ ObjCMethodDecl *GetterMethod =
+ IMPDecl->getInstanceMethod(Property->getGetterName());
+ ObjCMethodDecl *SetterMethod =
+ IMPDecl->getInstanceMethod(Property->getSetterName());
+ if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
+ SourceLocation MethodLoc =
+ (GetterMethod ? GetterMethod->getLocation()
+ : SetterMethod->getLocation());
+ Diag(MethodLoc, diag::warn_atomic_property_rule)
+ << Property->getIdentifier();
+ Diag(Property->getLocation(), diag::note_property_declare);
+ }
+ }
+ }
+}
+
/// ActOnForwardClassDeclaration -
Action::DeclPtrTy
Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
unsigned NumElts) {
llvm::SmallVector<ObjCInterfaceDecl*, 32> Interfaces;
@@ -1153,18 +1197,23 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
if (!IDecl) { // Not already seen? Make a forward decl.
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
- IdentList[i],
- // FIXME: need to get the 'real'
- // identifier loc from the parser.
- AtClassLoc, true);
- PushOnScopeChains(IDecl, TUScope);
+ IdentList[i], IdentLocs[i], true);
+
+ // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to
+ // the current DeclContext. This prevents clients that walk DeclContext
+ // from seeing the imaginary ObjCInterfaceDecl until it is actually
+ // declared later (if at all). We also take care to explicitly make
+ // sure this declaration is visible for name lookup.
+ PushOnScopeChains(IDecl, TUScope, false);
+ CurContext->makeDeclVisibleInContext(IDecl, true);
}
Interfaces.push_back(IDecl);
}
+ assert(Interfaces.size() == NumElts);
ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
- &Interfaces[0],
+ Interfaces.data(), IdentLocs,
Interfaces.size());
CurContext->addDecl(CDecl);
CheckObjCDeclScope(CDecl);
@@ -1524,12 +1573,17 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
// should be true.
if (!ClassDecl)
return;
-
+
bool isInterfaceDeclKind =
isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
|| isa<ObjCProtocolDecl>(ClassDecl);
bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
+ if (!isInterfaceDeclKind && AtEndLoc.isInvalid()) {
+ AtEndLoc = ClassDecl->getLocation();
+ Diag(AtEndLoc, diag::warn_missing_atend);
+ }
+
DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
@@ -1608,8 +1662,10 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
}
if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
IC->setAtEndLoc(AtEndLoc);
- if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
+ if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {
ImplMethodsVsClassMethods(IC, IDecl);
+ AtomicPropertySetterGetterRules(IC, IDecl);
+ }
} else if (ObjCCategoryImplDecl* CatImplClass =
dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
CatImplClass->setAtEndLoc(AtEndLoc);
@@ -1910,13 +1966,12 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
// with continuation class's readwrite property attribute!
unsigned PIkind = PIDecl->getPropertyAttributes();
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
- unsigned assignRetainCopyNonatomic =
- (ObjCPropertyDecl::OBJC_PR_assign |
- ObjCPropertyDecl::OBJC_PR_retain |
+ unsigned retainCopyNonatomic =
+ (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy |
ObjCPropertyDecl::OBJC_PR_nonatomic);
- if ((Attributes & assignRetainCopyNonatomic) !=
- (PIkind & assignRetainCopyNonatomic)) {
+ if ((Attributes & retainCopyNonatomic) !=
+ (PIkind & retainCopyNonatomic)) {
Diag(AtLoc, diag::warn_property_attr_mismatch);
Diag(PIDecl->getLocation(), diag::note_property_declare);
}
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index bdd00b84049d..25af0528d8b5 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -183,7 +183,7 @@ bool Sema::CheckExceptionSpecSubset(
SubIsPointer = true;
}
bool SubIsClass = CanonicalSubT->isRecordType();
- CanonicalSubT = CanonicalSubT.getUnqualifiedType();
+ CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
@@ -205,7 +205,7 @@ bool Sema::CheckExceptionSpecSubset(
continue;
}
}
- CanonicalSuperT = CanonicalSuperT.getUnqualifiedType();
+ CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
// If the types are the same, move on to the next type in the subset.
if (CanonicalSubT == CanonicalSuperT) {
Contained = true;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f1d6f2bb17ce..4f08ffe9db94 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -25,6 +26,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Designator.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
using namespace clang;
@@ -622,14 +624,12 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
ASTTemplateArgsPtr TemplateArgsPtr(*this,
Name.TemplateId->getTemplateArgs(),
- Name.TemplateId->getTemplateArgIsType(),
Name.TemplateId->NumArgs);
return ActOnTemplateIdExpr(SS,
TemplateTy::make(Name.TemplateId->Template),
Name.TemplateId->TemplateNameLoc,
Name.TemplateId->LAngleLoc,
TemplateArgsPtr,
- Name.TemplateId->getTemplateArgLocations(),
Name.TemplateId->RAngleLoc);
}
@@ -682,15 +682,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
isAddressOfOperand));
}
- LookupResult Lookup;
- LookupParsedName(Lookup, S, SS, Name, LookupOrdinaryName, false, true, Loc);
+ LookupResult Lookup(*this, Name, Loc, LookupOrdinaryName);
+ LookupParsedName(Lookup, S, SS, true);
- if (Lookup.isAmbiguous()) {
- DiagnoseAmbiguousLookup(Lookup, Name, Loc,
- SS && SS->isSet() ? SS->getRange()
- : SourceRange());
+ if (Lookup.isAmbiguous())
return ExprError();
- }
NamedDecl *D = Lookup.getAsSingleDecl(Context);
@@ -814,22 +810,18 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// information to check this property.
if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
Scope *CheckS = S;
- while (CheckS) {
+ while (CheckS && CheckS->getControlParent()) {
if (CheckS->isWithinElse() &&
CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
- if (Var->getType()->isBooleanType())
- ExprError(Diag(Loc, diag::warn_value_always_false)
- << Var->getDeclName());
- else
- ExprError(Diag(Loc, diag::warn_value_always_zero)
- << Var->getDeclName());
+ ExprError(Diag(Loc, diag::warn_value_always_zero)
+ << Var->getDeclName()
+ << (Var->getType()->isPointerType()? 2 :
+ Var->getType()->isBooleanType()? 1 : 0));
break;
}
- // Move up one more control parent to check again.
- CheckS = CheckS->getControlParent();
- if (CheckS)
- CheckS = CheckS->getParent();
+ // Move to the parent of this scope.
+ CheckS = CheckS->getParent();
}
}
} else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) {
@@ -986,7 +978,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
return BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
false, false, SS);
- else if (UnresolvedUsingDecl *UD = dyn_cast<UnresolvedUsingDecl>(D))
+ else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D))
return BuildDeclRefExpr(UD, Context.DependentTy, Loc,
/*TypeDependent=*/true,
/*ValueDependent=*/true, SS);
@@ -1441,10 +1433,6 @@ QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
Action::OwningExprResult
Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Kind, ExprArg Input) {
- // Since this might be a postfix expression, get rid of ParenListExprs.
- Input = MaybeConvertParenListExprToParenExpr(S, move(Input));
- Expr *Arg = (Expr *)Input.get();
-
UnaryOperator::Opcode Opc;
switch (Kind) {
default: assert(0 && "Unknown unary op!");
@@ -1452,124 +1440,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
case tok::minusminus: Opc = UnaryOperator::PostDec; break;
}
- if (getLangOptions().CPlusPlus &&
- (Arg->getType()->isRecordType() || Arg->getType()->isEnumeralType())) {
- // Which overloaded operator?
- OverloadedOperatorKind OverOp =
- (Opc == UnaryOperator::PostInc)? OO_PlusPlus : OO_MinusMinus;
-
- // C++ [over.inc]p1:
- //
- // [...] If the function is a member function with one
- // parameter (which shall be of type int) or a non-member
- // function with two parameters (the second of which shall be
- // of type int), it defines the postfix increment operator ++
- // for objects of that type. When the postfix increment is
- // called as a result of using the ++ operator, the int
- // argument will have value zero.
- Expr *Args[2] = {
- Arg,
- new (Context) IntegerLiteral(llvm::APInt(Context.Target.getIntWidth(), 0,
- /*isSigned=*/true), Context.IntTy, SourceLocation())
- };
-
- // Build the candidate set for overloading
- OverloadCandidateSet CandidateSet;
- AddOperatorCandidates(OverOp, S, OpLoc, Args, 2, CandidateSet);
-
- // Perform overload resolution.
- OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
- case OR_Success: {
- // We found a built-in operator or an overloaded operator.
- FunctionDecl *FnDecl = Best->Function;
-
- if (FnDecl) {
- // We matched an overloaded operator. Build a call to that
- // operator.
-
- // Convert the arguments.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
- if (PerformObjectArgumentInitialization(Arg, Method))
- return ExprError();
- } else {
- // Convert the arguments.
- if (PerformCopyInitialization(Arg,
- FnDecl->getParamDecl(0)->getType(),
- "passing"))
- return ExprError();
- }
-
- // Determine the result type
- QualType ResultTy = FnDecl->getResultType().getNonReferenceType();
-
- // Build the actual expression node.
- Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
- SourceLocation());
- UsualUnaryConversions(FnExpr);
-
- Input.release();
- Args[0] = Arg;
-
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, OverOp,
- FnExpr, Args, 2,
- ResultTy, OpLoc));
-
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(),
- FnDecl))
- return ExprError();
- return Owned(TheCall.release());
-
- } else {
- // We matched a built-in operator. Convert the arguments, then
- // break out so that we will build the appropriate built-in
- // operator node.
- if (PerformCopyInitialization(Arg, Best->BuiltinTypes.ParamTypes[0],
- "passing"))
- return ExprError();
-
- break;
- }
- }
-
- case OR_No_Viable_Function: {
- // No viable function; try checking this as a built-in operator, which
- // will fail and provide a diagnostic. Then, print the overload
- // candidates.
- OwningExprResult Result = CreateBuiltinUnaryOp(OpLoc, Opc, move(Input));
- assert(Result.isInvalid() &&
- "C++ postfix-unary operator overloading is missing candidates!");
- if (Result.isInvalid())
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
-
- return move(Result);
- }
-
- case OR_Ambiguous:
- Diag(OpLoc, diag::err_ovl_ambiguous_oper)
- << UnaryOperator::getOpcodeStr(Opc)
- << Arg->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
-
- case OR_Deleted:
- Diag(OpLoc, diag::err_ovl_deleted_oper)
- << Best->Function->isDeleted()
- << UnaryOperator::getOpcodeStr(Opc)
- << Arg->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
- }
-
- // Either we found no viable overloaded operator or we matched a
- // built-in operator. In either case, fall through to trying to
- // build a built-in operation.
- }
-
- Input.release();
- Input = Arg;
- return CreateBuiltinUnaryOp(OpLoc, Opc, move(Input));
+ return BuildUnaryOp(S, OpLoc, Opc, move(Input));
}
Action::OwningExprResult
@@ -1886,6 +1757,38 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
DefaultFunctionArrayConversion(BaseExpr);
QualType BaseType = BaseExpr->getType();
+
+ // If the user is trying to apply -> or . to a function pointer
+ // type, it's probably because the forgot parentheses to call that
+ // function. Suggest the addition of those parentheses, build the
+ // call, and continue on.
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+ if (const FunctionProtoType *Fun
+ = Ptr->getPointeeType()->getAs<FunctionProtoType>()) {
+ QualType ResultTy = Fun->getResultType();
+ if (Fun->getNumArgs() == 0 &&
+ ((OpKind == tok::period && ResultTy->isRecordType()) ||
+ (OpKind == tok::arrow && ResultTy->isPointerType() &&
+ ResultTy->getAs<PointerType>()->getPointeeType()
+ ->isRecordType()))) {
+ SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+ Diag(Loc, diag::err_member_reference_needs_call)
+ << QualType(Fun, 0)
+ << CodeModificationHint::CreateInsertion(Loc, "()");
+
+ OwningExprResult NewBase
+ = ActOnCallExpr(S, ExprArg(*this, BaseExpr), Loc,
+ MultiExprArg(*this, 0, 0), 0, Loc);
+ if (NewBase.isInvalid())
+ return move(NewBase);
+
+ BaseExpr = NewBase.takeAs<Expr>();
+ DefaultFunctionArrayConversion(BaseExpr);
+ BaseType = BaseExpr->getType();
+ }
+ }
+ }
+
// If this is an Objective-C pseudo-builtin and a definition is provided then
// use that.
if (BaseType->isObjCIdType()) {
@@ -2048,17 +1951,14 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
}
// The record definition is complete, now make sure the member is valid.
- LookupResult Result;
- LookupQualifiedName(Result, DC, MemberName, LookupMemberName, false);
+ LookupResult Result(*this, MemberName, MemberLoc, LookupMemberName);
+ LookupQualifiedName(Result, DC);
if (Result.empty())
return ExprError(Diag(MemberLoc, diag::err_no_member)
<< MemberName << DC << BaseExpr->getSourceRange());
- if (Result.isAmbiguous()) {
- DiagnoseAmbiguousLookup(Result, MemberName, MemberLoc,
- BaseExpr->getSourceRange());
+ if (Result.isAmbiguous())
return ExprError();
- }
NamedDecl *MemberDecl = Result.getAsSingleDecl(Context);
@@ -2356,16 +2256,6 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
MemberLoc, BaseExpr));
}
- for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
- E = OPT->qual_end(); I != E; ++I)
- if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
- // Check whether we can reference this property.
- if (DiagnoseUseOfDecl(PD, MemberLoc))
- return ExprError();
-
- return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
- MemberLoc, BaseExpr));
- }
// If that failed, look for an "implicit" property by seeing if the nullary
// selector is implemented.
@@ -2441,18 +2331,6 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
<< BaseType << BaseExpr->getSourceRange();
- // If the user is trying to apply -> or . to a function or function
- // pointer, it's probably because they forgot parentheses to call
- // the function. Suggest the addition of those parentheses.
- if (BaseType == Context.OverloadTy ||
- BaseType->isFunctionType() ||
- (BaseType->isPointerType() &&
- BaseType->getAs<PointerType>()->isFunctionType())) {
- SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
- Diag(Loc, diag::note_member_reference_needs_call)
- << CodeModificationHint::CreateInsertion(Loc, "()");
- }
-
return ExprError();
}
@@ -2485,12 +2363,10 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base,
// Translate the parser's template argument list in our AST format.
ASTTemplateArgsPtr TemplateArgsPtr(*this,
Member.TemplateId->getTemplateArgs(),
- Member.TemplateId->getTemplateArgIsType(),
Member.TemplateId->NumArgs);
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsPtr,
- Member.TemplateId->getTemplateArgLocations(),
TemplateArgs);
TemplateArgsPtr.release();
@@ -2639,6 +2515,9 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// Pass the argument.
if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
return true;
+
+ if (!ProtoArgType->isReferenceType())
+ Arg = MaybeBindToTemporary(Arg).takeAs<Expr>();
} else {
ParmVarDecl *Param = FDecl->getParamDecl(i);
@@ -2663,7 +2542,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
CallType = VariadicMethod;
// Promote the arguments (C99 6.5.2.2p7).
- for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+ for (unsigned i = NumArgsInProto; i < NumArgs; i++) {
Expr *Arg = Args[i];
Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType);
Call->setArg(i, Arg);
@@ -3054,8 +2933,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
static CastExpr::CastKind getScalarCastKind(ASTContext &Context,
QualType SrcTy, QualType DestTy) {
- if (Context.getCanonicalType(SrcTy).getUnqualifiedType() ==
- Context.getCanonicalType(DestTy).getUnqualifiedType())
+ if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
return CastExpr::CK_NoOp;
if (SrcTy->hasPointerRepresentation()) {
@@ -3106,8 +2984,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
}
if (!castType->isScalarType() && !castType->isVectorType()) {
- if (Context.getCanonicalType(castType).getUnqualifiedType() ==
- Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) &&
+ if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) &&
(castType->isStructureType() || castType->isUnionType())) {
// GCC struct/union extension: allow cast to self.
// FIXME: Check that the cast destination type is complete.
@@ -3123,8 +3000,8 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
RecordDecl::field_iterator Field, FieldEnd;
for (Field = RD->field_begin(), FieldEnd = RD->field_end();
Field != FieldEnd; ++Field) {
- if (Context.getCanonicalType(Field->getType()).getUnqualifiedType() ==
- Context.getCanonicalType(castExpr->getType()).getUnqualifiedType()) {
+ if (Context.hasSameUnqualifiedType(Field->getType(),
+ castExpr->getType())) {
Diag(TyR.getBegin(), diag::ext_typecheck_cast_to_union)
<< castExpr->getSourceRange();
break;
@@ -3570,9 +3447,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+ ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp);
// Promote to void*.
- ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
return destType;
}
@@ -3731,6 +3608,24 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
return ConvTy;
return IncompatiblePointerSign;
}
+
+ // If we are a multi-level pointer, it's possible that our issue is simply
+ // one of qualification - e.g. char ** -> const char ** is not allowed. If
+ // the eventual target type is the same and the pointers have the same
+ // level of indirection, this must be the issue.
+ if (lhptee->isPointerType() && rhptee->isPointerType()) {
+ do {
+ lhptee = lhptee->getAs<PointerType>()->getPointeeType();
+ rhptee = rhptee->getAs<PointerType>()->getPointeeType();
+
+ lhptee = Context.getCanonicalType(lhptee);
+ rhptee = Context.getCanonicalType(rhptee);
+ } while (lhptee->isPointerType() && rhptee->isPointerType());
+
+ if (Context.hasSameUnqualifiedType(lhptee, rhptee))
+ return IncompatibleNestedPointerQualifiers;
+ }
+
// General pointer incompatibility takes priority over qualifiers.
return IncompatiblePointer;
}
@@ -3757,7 +3652,7 @@ Sema::CheckBlockPointerTypesForAssignment(QualType lhsType,
AssignConvertType ConvTy = Compatible;
// For blocks we enforce that qualifiers are identical.
- if (lhptee.getCVRQualifiers() != rhptee.getCVRQualifiers())
+ if (lhptee.getLocalCVRQualifiers() != rhptee.getLocalCVRQualifiers())
ConvTy = CompatiblePointerDiscardsQualifiers;
if (!Context.typesAreCompatible(lhptee, rhptee))
@@ -4429,26 +4324,51 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return LHSTy;
}
-/// Implements -Wsign-compare.
+/// \brief Implements -Wsign-compare.
+///
+/// \param lex the left-hand expression
+/// \param rex the right-hand expression
+/// \param OpLoc the location of the joining operator
+/// \param Equality whether this is an "equality-like" join, which
+/// suppresses the warning in some cases
void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
- const PartialDiagnostic &PD) {
+ const PartialDiagnostic &PD, bool Equality) {
+ // Don't warn if we're in an unevaluated context.
+ if (ExprEvalContext == Unevaluated)
+ return;
+
QualType lt = lex->getType(), rt = rex->getType();
// Only warn if both operands are integral.
if (!lt->isIntegerType() || !rt->isIntegerType())
return;
+ // If either expression is value-dependent, don't warn. We'll get another
+ // chance at instantiation time.
+ if (lex->isValueDependent() || rex->isValueDependent())
+ return;
+
// The rule is that the signed operand becomes unsigned, so isolate the
// signed operand.
- Expr *signedOperand;
+ Expr *signedOperand, *unsignedOperand;
if (lt->isSignedIntegerType()) {
if (rt->isSignedIntegerType()) return;
signedOperand = lex;
+ unsignedOperand = rex;
} else {
if (!rt->isSignedIntegerType()) return;
signedOperand = rex;
+ unsignedOperand = lex;
}
+ // If the unsigned type is strictly smaller than the signed type,
+ // then (1) the result type will be signed and (2) the unsigned
+ // value will fit fully within the signed type, and thus the result
+ // of the comparison will be exact.
+ if (Context.getIntWidth(signedOperand->getType()) >
+ Context.getIntWidth(unsignedOperand->getType()))
+ return;
+
// If the value is a non-negative integer constant, then the
// signed->unsigned conversion won't change it.
llvm::APSInt value;
@@ -4459,6 +4379,20 @@ void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
return;
}
+ if (Equality) {
+ // For (in)equality comparisons, if the unsigned operand is a
+ // constant which cannot collide with a overflowed signed operand,
+ // then reinterpreting the signed operand as unsigned will not
+ // change the result of the comparison.
+ if (unsignedOperand->isIntegerConstantExpr(value, Context)) {
+ assert(!value.isSigned() && "result of unsigned expression is signed");
+
+ // 2's complement: test the top bit.
+ if (value.isNonNegative())
+ return;
+ }
+ }
+
Diag(OpLoc, PD)
<< lex->getType() << rex->getType()
<< lex->getSourceRange() << rex->getSourceRange();
@@ -4472,7 +4406,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
- CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison);
+ CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison,
+ (Opc == BinaryOperator::EQ || Opc == BinaryOperator::NE));
// C99 6.5.8p3 / C99 6.5.9p4
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
@@ -5637,7 +5572,8 @@ Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
UnaryOperator::Opcode Opc,
ExprArg input) {
Expr *Input = (Expr*)input.get();
- if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType()) {
+ if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() &&
+ Opc != UnaryOperator::Extension) {
// Find all of the overloaded operators visible from this
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
@@ -5814,8 +5750,8 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
}
}
- LookupResult R;
- LookupQualifiedName(R, RD, OC.U.IdentInfo, LookupMemberName);
+ LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
+ LookupQualifiedName(R, RD);
FieldDecl *MemberDecl
= dyn_cast_or_null<FieldDecl>(R.getAsSingleDecl(Context));
@@ -5828,7 +5764,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
// FIXME: Verify that MemberDecl isn't a bitfield.
if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) {
Res = BuildAnonymousStructUnionMemberReference(
- SourceLocation(), MemberDecl, Res, SourceLocation()).takeAs<Expr>();
+ OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
} else {
// MemberDecl->getType() doesn't get the right qualifiers, but it
// doesn't matter here.
@@ -6127,6 +6063,34 @@ Sema::OwningExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
}
+static void
+MakeObjCStringLiteralCodeModificationHint(Sema& SemaRef,
+ QualType DstType,
+ Expr *SrcExpr,
+ CodeModificationHint &Hint) {
+ if (!SemaRef.getLangOptions().ObjC1)
+ return;
+
+ const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
+ if (!PT)
+ return;
+
+ // Check if the destination is of type 'id'.
+ if (!PT->isObjCIdType()) {
+ // Check if the destination is the 'NSString' interface.
+ const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+ if (!ID || !ID->getIdentifier()->isStr("NSString"))
+ return;
+ }
+
+ // Strip off any parens and casts.
+ StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts());
+ if (!SL || SL->isWide())
+ return;
+
+ Hint = CodeModificationHint::CreateInsertion(SL->getLocStart(), "@");
+}
+
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
@@ -6134,6 +6098,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
// Decode the result (notice that AST's are still created for extensions).
bool isInvalid = false;
unsigned DiagKind;
+ CodeModificationHint Hint;
+
switch (ConvTy) {
default: assert(0 && "Unknown conversion type");
case Compatible: return false;
@@ -6144,6 +6110,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
DiagKind = diag::ext_typecheck_convert_int_pointer;
break;
case IncompatiblePointer:
+ MakeObjCStringLiteralCodeModificationHint(*this, DstType, SrcExpr, Hint);
DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
break;
case IncompatiblePointerSign:
@@ -6167,6 +6134,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
return false;
DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
break;
+ case IncompatibleNestedPointerQualifiers:
+ DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+ break;
case IntToBlockPointer:
DiagKind = diag::err_int_to_block_pointer;
break;
@@ -6188,7 +6158,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
}
Diag(Loc, DiagKind) << DstType << SrcType << Flavor
- << SrcExpr->getSourceRange();
+ << SrcExpr->getSourceRange() << Hint;
return isInvalid;
}
@@ -6405,11 +6375,29 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
SourceLocation Loc;
+ unsigned diagnostic = diag::warn_condition_is_assignment;
+
if (isa<BinaryOperator>(E)) {
BinaryOperator *Op = cast<BinaryOperator>(E);
if (Op->getOpcode() != BinaryOperator::Assign)
return;
+ // Greylist some idioms by putting them into a warning subcategory.
+ if (ObjCMessageExpr *ME
+ = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
+ Selector Sel = ME->getSelector();
+
+ // self = [<foo> init...]
+ if (isSelfExpr(Op->getLHS())
+ && Sel.getIdentifierInfoForSlot(0)->getName().startswith("init"))
+ diagnostic = diag::warn_condition_is_idiomatic_assignment;
+
+ // <foo> = [<bar> nextObject]
+ else if (Sel.isUnarySelector() &&
+ Sel.getIdentifierInfoForSlot(0)->getName() == "nextObject")
+ diagnostic = diag::warn_condition_is_idiomatic_assignment;
+ }
+
Loc = Op->getOperatorLoc();
} else if (isa<CXXOperatorCallExpr>(E)) {
CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E);
@@ -6425,7 +6413,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
SourceLocation Open = E->getSourceRange().getBegin();
SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
- Diag(Loc, diag::warn_condition_is_assignment)
+ Diag(Loc, diagnostic)
<< E->getSourceRange()
<< CodeModificationHint::CreateInsertion(Open, "(")
<< CodeModificationHint::CreateInsertion(Close, ")");
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index dc5768157356..0eea169b0727 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ExprCXX.h"
@@ -34,8 +35,8 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
TyOrExpr = GetTypeFromParser(TyOrExpr).getAsOpaquePtr();
IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
- LookupResult R;
- LookupQualifiedName(R, StdNamespace, TypeInfoII, LookupTagName);
+ LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
+ LookupQualifiedName(R, StdNamespace);
Decl *TypeInfoDecl = R.getAsSingleDecl(Context);
RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null<RecordDecl>(TypeInfoDecl);
if (!TypeInfoRecordDecl)
@@ -424,14 +425,13 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
Expr **ConsArgs = (Expr**)ConstructorArgs.get();
const RecordType *RT;
unsigned NumConsArgs = ConstructorArgs.size();
-
+ ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this);
+
if (AllocType->isDependentType() ||
Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
// Skip all the checks.
} else if ((RT = AllocType->getAs<RecordType>()) &&
!AllocType->isAggregateType()) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this);
-
Constructor = PerformInitializationByConstructor(
AllocType, move(ConstructorArgs),
TypeLoc,
@@ -568,8 +568,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
DeclarationName Name, Expr** Args,
unsigned NumArgs, DeclContext *Ctx,
bool AllowMissing, FunctionDecl *&Operator) {
- LookupResult R;
- LookupQualifiedName(R, Ctx, Name, LookupOrdinaryName);
+ LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);
+ LookupQualifiedName(R, Ctx);
if (R.empty()) {
if (AllowMissing)
return false;
@@ -754,6 +754,57 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
((DeclContext *)TUScope->getEntity())->addDecl(Alloc);
}
+bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+ DeclarationName Name,
+ FunctionDecl* &Operator) {
+ LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
+ // Try to find operator delete/operator delete[] in class scope.
+ LookupQualifiedName(Found, RD);
+
+ if (Found.isAmbiguous())
+ return true;
+
+ for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+ F != FEnd; ++F) {
+ if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
+ if (Delete->isUsualDeallocationFunction()) {
+ Operator = Delete;
+ return false;
+ }
+ }
+
+ // We did find operator delete/operator delete[] declarations, but
+ // none of them were suitable.
+ if (!Found.empty()) {
+ Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
+ << Name << RD;
+
+ for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+ F != FEnd; ++F) {
+ Diag((*F)->getLocation(),
+ diag::note_delete_member_function_declared_here)
+ << Name;
+ }
+
+ return true;
+ }
+
+ // Look for a global declaration.
+ DeclareGlobalNewDelete();
+ DeclContext *TUDecl = Context.getTranslationUnitDecl();
+
+ CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation());
+ Expr* DeallocArgs[1];
+ DeallocArgs[0] = &Null;
+ if (FindAllocationOverload(StartLoc, SourceRange(), Name,
+ DeallocArgs, 1, TUDecl, /*AllowMissing=*/false,
+ Operator))
+ return true;
+
+ assert(Operator && "Did not find a deallocation function!");
+ return false;
+}
+
/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
/// @code ::delete ptr; @endcode
/// or
@@ -845,32 +896,21 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
ArrayForm ? OO_Array_Delete : OO_Delete);
- if (Pointee->isRecordType() && !UseGlobal) {
- CXXRecordDecl *Record
- = cast<CXXRecordDecl>(Pointee->getAs<RecordType>()->getDecl());
-
- // Try to find operator delete/operator delete[] in class scope.
- LookupResult Found;
- LookupQualifiedName(Found, Record, DeleteName, LookupOrdinaryName);
- // FIXME: Diagnose ambiguity properly
- assert(!Found.isAmbiguous() && "Ambiguous delete/delete[] not handled");
- for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
- F != FEnd; ++F) {
- if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
- if (Delete->isUsualDeallocationFunction()) {
- OperatorDelete = Delete;
- break;
- }
- }
+ if (const RecordType *RT = Pointee->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ if (!UseGlobal &&
+ FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete))
+ return ExprError();
- if (!Record->hasTrivialDestructor())
- if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context))
+ if (!RD->hasTrivialDestructor())
+ if (const CXXDestructorDecl *Dtor = RD->getDestructor(Context))
MarkDeclarationReferenced(StartLoc,
const_cast<CXXDestructorDecl*>(Dtor));
}
-
+
if (!OperatorDelete) {
- // Didn't find a member overload. Look for a global one.
+ // Look for a global declaration.
DeclareGlobalNewDelete();
DeclContext *TUDecl = Context.getTranslationUnitDecl();
if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
@@ -1064,10 +1104,11 @@ Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
const ImplicitConversionSequence &ICS,
- const char* Flavor) {
+ const char* Flavor, bool IgnoreBaseAccess) {
switch (ICS.ConversionKind) {
case ImplicitConversionSequence::StandardConversion:
- if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor))
+ if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor,
+ IgnoreBaseAccess))
return true;
break;
@@ -1086,18 +1127,22 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
} else if (const CXXConstructorDecl *Ctor =
dyn_cast<CXXConstructorDecl>(FD)) {
CastKind = CastExpr::CK_ConstructorConversion;
-
- // If the user-defined conversion is specified by a constructor, the
- // initial standard conversion sequence converts the source type to the
- // type required by the argument of the constructor
- BeforeToType = Ctor->getParamDecl(0)->getType();
+ // Do no conversion if dealing with ... for the first conversion.
+ if (!ICS.UserDefined.EllipsisConversion)
+ // If the user-defined conversion is specified by a constructor, the
+ // initial standard conversion sequence converts the source type to the
+ // type required by the argument of the constructor
+ BeforeToType = Ctor->getParamDecl(0)->getType();
}
else
assert(0 && "Unknown conversion function kind!");
-
- if (PerformImplicitConversion(From, BeforeToType,
- ICS.UserDefined.Before, "converting"))
- return true;
+ // Whatch out for elipsis conversion.
+ if (!ICS.UserDefined.EllipsisConversion) {
+ if (PerformImplicitConversion(From, BeforeToType,
+ ICS.UserDefined.Before, "converting",
+ IgnoreBaseAccess))
+ return true;
+ }
OwningExprResult CastArg
= BuildCXXCastArgument(From->getLocStart(),
@@ -1145,7 +1190,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
const StandardConversionSequence& SCS,
- const char *Flavor) {
+ const char *Flavor, bool IgnoreBaseAccess) {
// Overall FIXME: we are recomputing too many types here and doing far too
// much extra work. What this means is that we need to keep track of more
// information that is computed when we try the implicit conversion initially,
@@ -1273,7 +1318,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- if (CheckPointerConversion(From, ToType, Kind))
+ if (CheckPointerConversion(From, ToType, Kind, IgnoreBaseAccess))
return true;
ImpCastExprToType(From, ToType, Kind);
break;
@@ -1281,7 +1326,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
case ICK_Pointer_Member: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- if (CheckMemberPointerConversion(From, ToType, Kind))
+ if (CheckMemberPointerConversion(From, ToType, Kind, IgnoreBaseAccess))
return true;
if (CheckExceptionSpecCompatibility(From, ToType))
return true;
@@ -1292,6 +1337,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
ImpCastExprToType(From, Context.BoolTy, CastExpr::CK_Unknown);
break;
+ case ICK_Derived_To_Base:
+ if (CheckDerivedToBaseConversion(From->getType(),
+ ToType.getNonReferenceType(),
+ From->getLocStart(),
+ From->getSourceRange(),
+ IgnoreBaseAccess))
+ return true;
+ ImpCastExprToType(From, ToType.getNonReferenceType(),
+ CastExpr::CK_DerivedToBase);
+ break;
+
default:
assert(false && "Improper second standard conversion");
break;
@@ -1309,7 +1365,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
CastExpr::CK_NoOp,
ToType->isLValueReferenceType());
break;
-
+
default:
assert(false && "Improper second standard conversion");
break;
@@ -1374,8 +1430,7 @@ QualType Sema::CheckPointerToMemberOperands(
}
}
- if (Context.getCanonicalType(Class).getUnqualifiedType() !=
- Context.getCanonicalType(LType).getUnqualifiedType()) {
+ if (!Context.hasSameUnqualifiedType(Class, LType)) {
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
/*DetectVirtual=*/false);
// FIXME: Would it be useful to print full ambiguity paths, or is that
@@ -1827,8 +1882,6 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
!T2->isPointerType() && !T2->isMemberPointerType())
return QualType();
- // FIXME: Do we need to work on the canonical types?
-
// C++0x 5.9p2
// Pointer conversions and qualification conversions are performed on
// pointer operands to bring them to their composite pointer type. If
@@ -1850,8 +1903,8 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
}
// Now both have to be pointers or member pointers.
- if (!T1->isPointerType() && !T1->isMemberPointerType() &&
- !T2->isPointerType() && !T2->isMemberPointerType())
+ if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||
+ (!T2->isPointerType() && !T2->isMemberPointerType()))
return QualType();
// Otherwise, of one of the operands has type "pointer to cv1 void," then
@@ -1865,9 +1918,13 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
// conversions in both directions. If only one works, or if the two composite
// types are the same, we have succeeded.
// FIXME: extended qualifiers?
- llvm::SmallVector<unsigned, 4> QualifierUnion;
- llvm::SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass;
- QualType Composite1 = T1, Composite2 = T2;
+ typedef llvm::SmallVector<unsigned, 4> QualifierVector;
+ QualifierVector QualifierUnion;
+ typedef llvm::SmallVector<std::pair<const Type *, const Type *>, 4>
+ ContainingClassVector;
+ ContainingClassVector MemberOfClass;
+ QualType Composite1 = Context.getCanonicalType(T1),
+ Composite2 = Context.getCanonicalType(T2);
do {
const PointerType *Ptr1, *Ptr2;
if ((Ptr1 = Composite1->getAs<PointerType>()) &&
@@ -1899,11 +1956,11 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
} while (true);
// Rewrap the composites as pointers or member pointers with the union CVRs.
- llvm::SmallVector<std::pair<const Type *, const Type *>, 4>::iterator MOC
- = MemberOfClass.begin();
- for (llvm::SmallVector<unsigned, 4>::iterator
- I = QualifierUnion.begin(),
- E = QualifierUnion.end();
+ ContainingClassVector::reverse_iterator MOC
+ = MemberOfClass.rbegin();
+ for (QualifierVector::reverse_iterator
+ I = QualifierUnion.rbegin(),
+ E = QualifierUnion.rend();
I != E; (void)++I, ++MOC) {
Qualifiers Quals = Qualifiers::fromCVRMask(*I);
if (MOC->first && MOC->second) {
@@ -2085,12 +2142,19 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
return move(Base);
}
+ // The object type must be complete (or dependent).
+ if (!BaseType->isDependentType() &&
+ RequireCompleteType(OpLoc, BaseType,
+ PDiag(diag::err_incomplete_member_access)))
+ return ExprError();
+
// C++ [basic.lookup.classref]p2:
// If the id-expression in a class member access (5.2.5) is an
- // unqualified-id, and the type of the object expres- sion is of a class
+ // unqualified-id, and the type of the object expression is of a class
// type C (or of pointer to a class type C), the unqualified-id is looked
// up in the scope of class C. [...]
ObjectType = BaseType.getAsOpaquePtr();
+
return move(Base);
}
@@ -2108,7 +2172,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, 0, 0,
ResultType,
- SourceLocation());
+ Exp->getLocEnd());
return CE;
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 4746a2597e55..0f973d6d9ba3 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -174,7 +174,8 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
// copy-initialization where the cv-unqualified version of the
// source type is the same class as, or a derived class of, the
// class of the destination, constructors are considered.
- if ((DeclTypeC.getUnqualifiedType() == InitTypeC.getUnqualifiedType()) ||
+ if ((DeclTypeC.getLocalUnqualifiedType()
+ == InitTypeC.getLocalUnqualifiedType()) ||
IsDerivedFrom(InitTypeC, DeclTypeC)) {
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(DeclType->getAs<RecordType>()->getDecl());
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 93752e130c94..1f49b789d3f0 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
@@ -34,77 +35,161 @@
using namespace clang;
-typedef llvm::SmallVector<UsingDirectiveDecl*, 4> UsingDirectivesTy;
-typedef llvm::DenseSet<NamespaceDecl*> NamespaceSet;
+namespace {
+ class UnqualUsingEntry {
+ const DeclContext *Nominated;
+ const DeclContext *CommonAncestor;
-/// UsingDirAncestorCompare - Implements strict weak ordering of
-/// UsingDirectives. It orders them by address of its common ancestor.
-struct UsingDirAncestorCompare {
+ public:
+ UnqualUsingEntry(const DeclContext *Nominated,
+ const DeclContext *CommonAncestor)
+ : Nominated(Nominated), CommonAncestor(CommonAncestor) {
+ }
- /// @brief Compares UsingDirectiveDecl common ancestor with DeclContext.
- bool operator () (UsingDirectiveDecl *U, const DeclContext *Ctx) const {
- return U->getCommonAncestor() < Ctx;
- }
+ const DeclContext *getCommonAncestor() const {
+ return CommonAncestor;
+ }
- /// @brief Compares UsingDirectiveDecl common ancestor with DeclContext.
- bool operator () (const DeclContext *Ctx, UsingDirectiveDecl *U) const {
- return Ctx < U->getCommonAncestor();
- }
+ const DeclContext *getNominatedNamespace() const {
+ return Nominated;
+ }
- /// @brief Compares UsingDirectiveDecl common ancestors.
- bool operator () (UsingDirectiveDecl *U1, UsingDirectiveDecl *U2) const {
- return U1->getCommonAncestor() < U2->getCommonAncestor();
- }
-};
-
-/// AddNamespaceUsingDirectives - Adds all UsingDirectiveDecl's to heap UDirs
-/// (ordered by common ancestors), found in namespace NS,
-/// including all found (recursively) in their nominated namespaces.
-void AddNamespaceUsingDirectives(ASTContext &Context,
- DeclContext *NS,
- UsingDirectivesTy &UDirs,
- NamespaceSet &Visited) {
- DeclContext::udir_iterator I, End;
-
- for (llvm::tie(I, End) = NS->getUsingDirectives(); I !=End; ++I) {
- UDirs.push_back(*I);
- std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
- NamespaceDecl *Nominated = (*I)->getNominatedNamespace();
- if (Visited.insert(Nominated).second)
- AddNamespaceUsingDirectives(Context, Nominated, UDirs, /*ref*/ Visited);
- }
-}
+ // Sort by the pointer value of the common ancestor.
+ struct Comparator {
+ bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) {
+ return L.getCommonAncestor() < R.getCommonAncestor();
+ }
-/// AddScopeUsingDirectives - Adds all UsingDirectiveDecl's found in Scope S,
-/// including all found in the namespaces they nominate.
-static void AddScopeUsingDirectives(ASTContext &Context, Scope *S,
- UsingDirectivesTy &UDirs) {
- NamespaceSet VisitedNS;
+ bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) {
+ return E.getCommonAncestor() < DC;
+ }
- if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
+ bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) {
+ return DC < E.getCommonAncestor();
+ }
+ };
+ };
+
+ /// A collection of using directives, as used by C++ unqualified
+ /// lookup.
+ class UnqualUsingDirectiveSet {
+ typedef llvm::SmallVector<UnqualUsingEntry, 8> ListTy;
+
+ ListTy list;
+ llvm::SmallPtrSet<DeclContext*, 8> visited;
+
+ public:
+ UnqualUsingDirectiveSet() {}
+
+ void visitScopeChain(Scope *S, Scope *InnermostFileScope) {
+ // C++ [namespace.udir]p1:
+ // During unqualified name lookup, the names appear as if they
+ // were declared in the nearest enclosing namespace which contains
+ // both the using-directive and the nominated namespace.
+ DeclContext *InnermostFileDC
+ = static_cast<DeclContext*>(InnermostFileScope->getEntity());
+ assert(InnermostFileDC && InnermostFileDC->isFileContext());
+
+ for (; S; S = S->getParent()) {
+ if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
+ DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC);
+ visit(Ctx, EffectiveDC);
+ } else {
+ Scope::udir_iterator I = S->using_directives_begin(),
+ End = S->using_directives_end();
+
+ for (; I != End; ++I)
+ visit(I->getAs<UsingDirectiveDecl>(), InnermostFileDC);
+ }
+ }
+ }
- if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(Ctx))
- VisitedNS.insert(NS);
+ // Visits a context and collect all of its using directives
+ // recursively. Treats all using directives as if they were
+ // declared in the context.
+ //
+ // A given context is only every visited once, so it is important
+ // that contexts be visited from the inside out in order to get
+ // the effective DCs right.
+ void visit(DeclContext *DC, DeclContext *EffectiveDC) {
+ if (!visited.insert(DC))
+ return;
+
+ addUsingDirectives(DC, EffectiveDC);
+ }
- AddNamespaceUsingDirectives(Context, Ctx, UDirs, /*ref*/ VisitedNS);
+ // Visits a using directive and collects all of its using
+ // directives recursively. Treats all using directives as if they
+ // were declared in the effective DC.
+ void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+ DeclContext *NS = UD->getNominatedNamespace();
+ if (!visited.insert(NS))
+ return;
- } else {
- Scope::udir_iterator I = S->using_directives_begin(),
- End = S->using_directives_end();
-
- for (; I != End; ++I) {
- UsingDirectiveDecl *UD = I->getAs<UsingDirectiveDecl>();
- UDirs.push_back(UD);
- std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
-
- NamespaceDecl *Nominated = UD->getNominatedNamespace();
- if (!VisitedNS.count(Nominated)) {
- VisitedNS.insert(Nominated);
- AddNamespaceUsingDirectives(Context, Nominated, UDirs,
- /*ref*/ VisitedNS);
+ addUsingDirective(UD, EffectiveDC);
+ addUsingDirectives(NS, EffectiveDC);
+ }
+
+ // Adds all the using directives in a context (and those nominated
+ // by its using directives, transitively) as if they appeared in
+ // the given effective context.
+ void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
+ llvm::SmallVector<DeclContext*,4> queue;
+ while (true) {
+ DeclContext::udir_iterator I, End;
+ for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) {
+ UsingDirectiveDecl *UD = *I;
+ DeclContext *NS = UD->getNominatedNamespace();
+ if (visited.insert(NS)) {
+ addUsingDirective(UD, EffectiveDC);
+ queue.push_back(NS);
+ }
+ }
+
+ if (queue.empty())
+ return;
+
+ DC = queue.back();
+ queue.pop_back();
}
}
- }
+
+ // Add a using directive as if it had been declared in the given
+ // context. This helps implement C++ [namespace.udir]p3:
+ // The using-directive is transitive: if a scope contains a
+ // using-directive that nominates a second namespace that itself
+ // contains using-directives, the effect is as if the
+ // using-directives from the second namespace also appeared in
+ // the first.
+ void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+ // Find the common ancestor between the effective context and
+ // the nominated namespace.
+ DeclContext *Common = UD->getNominatedNamespace();
+ while (!Common->Encloses(EffectiveDC))
+ Common = Common->getParent();
+ Common = Common->getPrimaryContext();
+
+ list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
+ }
+
+ void done() {
+ std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
+ }
+
+ typedef ListTy::iterator iterator;
+ typedef ListTy::const_iterator const_iterator;
+
+ iterator begin() { return list.begin(); }
+ iterator end() { return list.end(); }
+ const_iterator begin() const { return list.begin(); }
+ const_iterator end() const { return list.end(); }
+
+ std::pair<const_iterator,const_iterator>
+ getNamespacesFor(DeclContext *DC) const {
+ return std::equal_range(begin(), end(), DC->getPrimaryContext(),
+ UnqualUsingEntry::Comparator());
+ }
+ };
}
// Retrieve the set of identifier namespaces that correspond to a
@@ -153,42 +238,50 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
}
// Necessary because CXXBasePaths is not complete in Sema.h
-void Sema::LookupResult::deletePaths(CXXBasePaths *Paths) {
+void LookupResult::deletePaths(CXXBasePaths *Paths) {
delete Paths;
}
-void Sema::LookupResult::resolveKind() {
+void LookupResult::resolveKind() {
unsigned N = Decls.size();
// Fast case: no possible ambiguity.
- if (N <= 1) return;
+ if (N == 0) return;
+ if (N == 1) {
+ if (isa<UnresolvedUsingValueDecl>(Decls[0]))
+ ResultKind = FoundUnresolvedValue;
+ return;
+ }
// Don't do any extra resolution if we've already resolved as ambiguous.
- if (Kind == Ambiguous) return;
+ if (ResultKind == Ambiguous) return;
llvm::SmallPtrSet<NamedDecl*, 16> Unique;
bool Ambiguous = false;
bool HasTag = false, HasFunction = false, HasNonFunction = false;
+ bool HasUnresolved = false;
unsigned UniqueTagIndex = 0;
unsigned I = 0;
while (I < N) {
- NamedDecl *D = Decls[I];
- assert(D == D->getUnderlyingDecl());
+ NamedDecl *D = Decls[I]->getUnderlyingDecl();
+ D = cast<NamedDecl>(D->getCanonicalDecl());
- NamedDecl *CanonD = cast<NamedDecl>(D->getCanonicalDecl());
- if (!Unique.insert(CanonD)) {
+ if (!Unique.insert(D)) {
// If it's not unique, pull something off the back (and
// continue at this index).
Decls[I] = Decls[--N];
- } else if (isa<UnresolvedUsingDecl>(D)) {
- // FIXME: proper support for UnresolvedUsingDecls.
+ } else if (isa<UnresolvedUsingValueDecl>(D)) {
+ // FIXME: support unresolved using value declarations
Decls[I] = Decls[--N];
} else {
// Otherwise, do some decl type analysis and then continue.
- if (isa<TagDecl>(D)) {
+
+ if (isa<UnresolvedUsingValueDecl>(D)) {
+ HasUnresolved = true;
+ } else if (isa<TagDecl>(D)) {
if (HasTag)
Ambiguous = true;
UniqueTagIndex = I;
@@ -213,7 +306,8 @@ void Sema::LookupResult::resolveKind() {
// wherever the object, function, or enumerator name is visible.
// But it's still an error if there are distinct tag types found,
// even if they're not visible. (ref?)
- if (HasTag && !Ambiguous && (HasFunction || HasNonFunction))
+ if (HideTags && HasTag && !Ambiguous && !HasUnresolved &&
+ (HasFunction || HasNonFunction))
Decls[UniqueTagIndex] = Decls[--N];
Decls.set_size(N);
@@ -223,10 +317,12 @@ void Sema::LookupResult::resolveKind() {
if (Ambiguous)
setAmbiguous(LookupResult::AmbiguousReference);
+ else if (HasUnresolved)
+ ResultKind = LookupResult::FoundUnresolvedValue;
else if (N > 1)
- Kind = LookupResult::FoundOverloaded;
+ ResultKind = LookupResult::FoundOverloaded;
else
- Kind = LookupResult::Found;
+ ResultKind = LookupResult::Found;
}
/// @brief Converts the result of name lookup into a single (possible
@@ -242,10 +338,10 @@ void Sema::LookupResult::resolveKind() {
/// solution, since it causes the OverloadedFunctionDecl to be
/// leaked. FIXME: Eventually, there will be a better way to iterate
/// over the set of overloaded functions returned by name lookup.
-NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const {
+NamedDecl *LookupResult::getAsSingleDecl(ASTContext &C) const {
size_t size = Decls.size();
if (size == 0) return 0;
- if (size == 1) return *begin();
+ if (size == 1) return (*begin())->getUnderlyingDecl();
if (isAmbiguous()) return 0;
@@ -255,9 +351,7 @@ NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const {
= OverloadedFunctionDecl::Create(C, (*I)->getDeclContext(),
(*I)->getDeclName());
for (; I != E; ++I) {
- NamedDecl *ND = *I;
- assert(ND->getUnderlyingDecl() == ND
- && "decls in lookup result should have redirections stripped");
+ NamedDecl *ND = (*I)->getUnderlyingDecl();
assert(ND->isFunctionOrFunctionTemplate());
if (isa<FunctionDecl>(ND))
Ovl->addOverload(cast<FunctionDecl>(ND));
@@ -269,7 +363,7 @@ NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const {
return Ovl;
}
-void Sema::LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
+void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
CXXBasePaths::paths_iterator I, E;
DeclContext::lookup_iterator DI, DE;
for (I = P.begin(), E = P.end(); I != E; ++I)
@@ -277,7 +371,7 @@ void Sema::LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
addDecl(*DI);
}
-void Sema::LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) {
+void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) {
Paths = new CXXBasePaths;
Paths->swap(P);
addDeclsFromBasePaths(*Paths);
@@ -285,7 +379,7 @@ void Sema::LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) {
setAmbiguous(AmbiguousBaseSubobjects);
}
-void Sema::LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
+void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
Paths = new CXXBasePaths;
Paths->swap(P);
addDeclsFromBasePaths(*Paths);
@@ -293,7 +387,7 @@ void Sema::LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
setAmbiguous(AmbiguousBaseSubobjectTypes);
}
-void Sema::LookupResult::print(llvm::raw_ostream &Out) {
+void LookupResult::print(llvm::raw_ostream &Out) {
Out << Decls.size() << " result(s)";
if (isAmbiguous()) Out << ", ambiguous";
if (Paths) Out << ", base paths present";
@@ -306,42 +400,36 @@ void Sema::LookupResult::print(llvm::raw_ostream &Out) {
// Adds all qualifying matches for a name within a decl context to the
// given lookup result. Returns true if any matches were found.
-static bool LookupDirect(Sema::LookupResult &R, DeclContext *DC,
- DeclarationName Name,
- Sema::LookupNameKind NameKind,
- unsigned IDNS) {
+static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
bool Found = false;
- DeclContext::lookup_iterator I, E;
- for (llvm::tie(I, E) = DC->lookup(Name); I != E; ++I)
- if (Sema::isAcceptableLookupResult(*I, NameKind, IDNS))
+ DeclContext::lookup_const_iterator I, E;
+ for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I)
+ if (Sema::isAcceptableLookupResult(*I, R.getLookupKind(),
+ R.getIdentifierNamespace()))
R.addDecl(*I), Found = true;
return Found;
}
+// Performs C++ unqualified lookup into the given file context.
static bool
-CppNamespaceLookup(Sema::LookupResult &R, ASTContext &Context, DeclContext *NS,
- DeclarationName Name, Sema::LookupNameKind NameKind,
- unsigned IDNS, UsingDirectivesTy *UDirs = 0) {
+CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS,
+ UnqualUsingDirectiveSet &UDirs) {
assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
- // Perform qualified name lookup into the LookupCtx.
- bool Found = LookupDirect(R, NS, Name, NameKind, IDNS);
-
- if (UDirs) {
- // For each UsingDirectiveDecl, which common ancestor is equal
- // to NS, we preform qualified name lookup into namespace nominated by it.
- UsingDirectivesTy::const_iterator UI, UEnd;
- llvm::tie(UI, UEnd) =
- std::equal_range(UDirs->begin(), UDirs->end(), NS,
- UsingDirAncestorCompare());
-
- for (; UI != UEnd; ++UI)
- if (LookupDirect(R, (*UI)->getNominatedNamespace(), Name, NameKind, IDNS))
- Found = true;
- }
+ // Perform direct name lookup into the LookupCtx.
+ bool Found = LookupDirect(R, NS);
+
+ // Perform direct name lookup into the namespaces nominated by the
+ // using directives whose common ancestor is this namespace.
+ UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+ llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
+
+ for (; UI != UEnd; ++UI)
+ if (LookupDirect(R, UI->getNominatedNamespace()))
+ Found = true;
R.resolveKind();
@@ -363,20 +451,23 @@ static DeclContext *findOuterContext(Scope *S) {
return 0;
}
-bool
-Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name,
- LookupNameKind NameKind, bool RedeclarationOnly) {
+bool Sema::CppLookupName(LookupResult &R, Scope *S) {
assert(getLangOptions().CPlusPlus &&
"Can perform only C++ lookup");
+ LookupNameKind NameKind = R.getLookupKind();
unsigned IDNS
= getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
// If we're testing for redeclarations, also look in the friend namespaces.
- if (RedeclarationOnly) {
+ if (R.isForRedeclaration()) {
if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend;
if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend;
}
+ R.setIdentifierNamespace(IDNS);
+
+ DeclarationName Name = R.getLookupName();
+
Scope *Initial = S;
IdentifierResolver::iterator
I = IdResolver.begin(Name),
@@ -427,24 +518,25 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name,
// example, inside a class without any base classes, we never need to
// perform qualified lookup because all of the members are on top of the
// identifier chain.
- if (LookupQualifiedName(R, Ctx, Name, NameKind, RedeclarationOnly))
+ if (LookupQualifiedName(R, Ctx))
return true;
}
}
}
+ // Stop if we ran out of scopes.
+ // FIXME: This really, really shouldn't be happening.
+ if (!S) return false;
+
// Collect UsingDirectiveDecls in all scopes, and recursively all
// nominated namespaces by those using-directives.
- // UsingDirectives are pushed to heap, in common ancestor pointer value order.
+ //
// FIXME: Cache this sorted list in Scope structure, and DeclContext, so we
// don't build it for each lookup!
- UsingDirectivesTy UDirs;
- for (Scope *SC = Initial; SC; SC = SC->getParent())
- if (SC->getFlags() & Scope::DeclScope)
- AddScopeUsingDirectives(Context, SC, UDirs);
- // Sort heapified UsingDirectiveDecls.
- std::sort_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
+ UnqualUsingDirectiveSet UDirs;
+ UDirs.visitScopeChain(Initial, S);
+ UDirs.done();
// Lookup namespace scope, and global scope.
// Unqualified name lookup in C++ requires looking into scopes
@@ -473,7 +565,7 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name,
}
// Look into context considering using-directives.
- if (CppNamespaceLookup(R, Context, Ctx, Name, NameKind, IDNS, &UDirs))
+ if (CppNamespaceLookup(R, Context, Ctx, UDirs))
Found = true;
if (Found) {
@@ -481,7 +573,7 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name,
return true;
}
- if (RedeclarationOnly && !Ctx->isTransparentContext())
+ if (R.isForRedeclaration() && !Ctx->isTransparentContext())
return false;
}
@@ -519,11 +611,12 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name,
/// @returns The result of name lookup, which includes zero or more
/// declarations and possibly additional information used to diagnose
/// ambiguities.
-bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name,
- LookupNameKind NameKind, bool RedeclarationOnly,
- bool AllowBuiltinCreation, SourceLocation Loc) {
+bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
+ DeclarationName Name = R.getLookupName();
if (!Name) return false;
+ LookupNameKind NameKind = R.getLookupKind();
+
if (!getLangOptions().CPlusPlus) {
// Unqualified name lookup in C/Objective-C is purely lexical, so
// search in the declarations attached to the name.
@@ -619,7 +712,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name,
}
} else {
// Perform C++ unqualified name lookup.
- if (CppLookupName(R, S, Name, NameKind, RedeclarationOnly))
+ if (CppLookupName(R, S))
return true;
}
@@ -639,7 +732,8 @@ bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name,
return false;
NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
- S, RedeclarationOnly, Loc);
+ S, R.isForRedeclaration(),
+ R.getNameLoc());
if (D) R.addDecl(D);
return (D != NULL);
}
@@ -674,11 +768,8 @@ bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name,
/// class or enumeration name if and only if the declarations are
/// from the same namespace; otherwise (the declarations are from
/// different namespaces), the program is ill-formed.
-static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R,
- DeclContext *StartDC,
- DeclarationName Name,
- Sema::LookupNameKind NameKind,
- unsigned IDNS) {
+static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
+ DeclContext *StartDC) {
assert(StartDC->isFileContext() && "start context is not a file context");
DeclContext::udir_iterator I = StartDC->using_directives_begin();
@@ -697,7 +788,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R,
// We have already looked into the initial namespace; seed the queue
// with its using-children.
for (; I != E; ++I) {
- NamespaceDecl *ND = (*I)->getNominatedNamespace();
+ NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
if (Visited.insert(ND).second)
Queue.push_back(ND);
}
@@ -709,7 +800,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R,
bool FoundTag = false;
bool FoundNonTag = false;
- Sema::LookupResult LocalR;
+ LookupResult LocalR(LookupResult::Temporary, R);
bool Found = false;
while (!Queue.empty()) {
@@ -719,8 +810,8 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R,
// We go through some convolutions here to avoid copying results
// between LookupResults.
bool UseLocal = !R.empty();
- Sema::LookupResult &DirectR = UseLocal ? LocalR : R;
- bool FoundDirect = LookupDirect(DirectR, ND, Name, NameKind, IDNS);
+ LookupResult &DirectR = UseLocal ? LocalR : R;
+ bool FoundDirect = LookupDirect(DirectR, ND);
if (FoundDirect) {
// First do any local hiding.
@@ -792,22 +883,23 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R,
/// @returns The result of name lookup, which includes zero or more
/// declarations and possibly additional information used to diagnose
/// ambiguities.
-bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
- DeclarationName Name, LookupNameKind NameKind,
- bool RedeclarationOnly) {
+bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) {
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
- if (!Name)
+ if (!R.getLookupName())
return false;
// If we're performing qualified name lookup (e.g., lookup into a
// struct), find fields as part of ordinary name lookup.
+ LookupNameKind NameKind = R.getLookupKind();
unsigned IDNS
= getIdentifierNamespacesFromLookupNameKind(NameKind,
getLangOptions().CPlusPlus);
if (NameKind == LookupOrdinaryName)
IDNS |= Decl::IDNS_Member;
+ R.setIdentifierNamespace(IDNS);
+
// Make sure that the declaration context is complete.
assert((!isa<TagDecl>(LookupCtx) ||
LookupCtx->isDependentContext() ||
@@ -817,7 +909,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
"Declaration context must already be complete!");
// Perform qualified name lookup into the LookupCtx.
- if (LookupDirect(R, LookupCtx, Name, NameKind, IDNS)) {
+ if (LookupDirect(R, LookupCtx)) {
R.resolveKind();
return true;
}
@@ -831,13 +923,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// the unqualified-id shall name a member of the namespace
// designated by the nested-name-specifier.
// See also [class.mfct]p5 and [class.static.data]p2.
- if (RedeclarationOnly)
+ if (R.isForRedeclaration())
return false;
- // If this is a namespace, look it up in
+ // If this is a namespace, look it up in the implied namespaces.
if (LookupCtx->isFileContext())
- return LookupQualifiedNameInUsingDirectives(R, LookupCtx, Name, NameKind,
- IDNS);
+ return LookupQualifiedNameInUsingDirectives(R, LookupCtx);
// If this isn't a C++ class, we aren't allowed to look into base
// classes, we're done.
@@ -851,7 +942,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// Look for this member in our base classes
CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0;
- switch (NameKind) {
+ switch (R.getLookupKind()) {
case LookupOrdinaryName:
case LookupMemberName:
case LookupRedeclarationWithLinkage:
@@ -875,7 +966,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
break;
}
- if (!LookupRec->lookupInBases(BaseCallback, Name.getAsOpaquePtr(), Paths))
+ if (!LookupRec->lookupInBases(BaseCallback,
+ R.getLookupName().getAsOpaquePtr(), Paths))
return false;
// C++ [class.member.lookup]p2:
@@ -977,10 +1069,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
///
/// @returns True if any decls were found (but possibly ambiguous)
bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
- DeclarationName Name, LookupNameKind NameKind,
- bool RedeclarationOnly, bool AllowBuiltinCreation,
- SourceLocation Loc,
- bool EnteringContext) {
+ bool AllowBuiltinCreation, bool EnteringContext) {
if (SS && SS->isInvalid()) {
// When the scope specifier is invalid, don't even look for
// anything.
@@ -994,7 +1083,9 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS))
return false;
- return LookupQualifiedName(R, DC, Name, NameKind, RedeclarationOnly);
+ R.setContextRange(SS->getRange());
+
+ return LookupQualifiedName(R, DC);
}
// We could not resolve the scope specified to a specific declaration
@@ -1004,8 +1095,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
}
// Perform unqualified name lookup starting in the given scope.
- return LookupName(R, S, Name, NameKind, RedeclarationOnly,
- AllowBuiltinCreation, Loc);
+ return LookupName(R, S, AllowBuiltinCreation);
}
@@ -1025,11 +1115,13 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
/// precedes the name.
///
/// @returns true
-bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
- SourceLocation NameLoc,
- SourceRange LookupRange) {
+bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
+ DeclarationName Name = Result.getLookupName();
+ SourceLocation NameLoc = Result.getNameLoc();
+ SourceRange LookupRange = Result.getContextRange();
+
switch (Result.getAmbiguityKind()) {
case LookupResult::AmbiguousBaseSubobjects: {
CXXBasePaths *Paths = Result.getBasePaths();
@@ -1136,12 +1228,13 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
AssociatedClasses);
break;
- case TemplateArgument::Declaration:
+ case TemplateArgument::Template: {
// [...] the namespaces in which any template template arguments are
// defined; and the classes in which any member templates used as
// template template arguments are defined.
+ TemplateName Template = Arg.getAsTemplate();
if (ClassTemplateDecl *ClassTemplate
- = dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) {
+ = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
DeclContext *Ctx = ClassTemplate->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
AssociatedClasses.insert(EnclosingClass);
@@ -1151,7 +1244,9 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
CollectNamespace(AssociatedNamespaces, Ctx);
}
break;
-
+ }
+
+ case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::Expression:
// [Note: non-type template arguments do not contribute to the set of
@@ -1490,8 +1585,7 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
if (T1->isEnumeralType()) {
QualType ArgType = Proto->getArgType(0).getNonReferenceType();
- if (Context.getCanonicalType(T1).getUnqualifiedType()
- == Context.getCanonicalType(ArgType).getUnqualifiedType())
+ if (Context.hasSameUnqualifiedType(T1, ArgType))
return true;
}
@@ -1500,14 +1594,21 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
if (!T2.isNull() && T2->isEnumeralType()) {
QualType ArgType = Proto->getArgType(1).getNonReferenceType();
- if (Context.getCanonicalType(T2).getUnqualifiedType()
- == Context.getCanonicalType(ArgType).getUnqualifiedType())
+ if (Context.hasSameUnqualifiedType(T2, ArgType))
return true;
}
return false;
}
+NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
+ LookupNameKind NameKind,
+ RedeclarationKind Redecl) {
+ LookupResult R(*this, Name, SourceLocation(), NameKind, Redecl);
+ LookupName(R, S);
+ return R.getAsSingleDecl(Context);
+}
+
/// \brief Find the protocol with the given name, if any.
ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
Decl *D = LookupSingleName(TUScope, II, LookupObjCProtocolName);
@@ -1537,8 +1638,8 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
// of type T2 or "reference to (possibly cv-qualified) T2",
// when T2 is an enumeration type, are candidate functions.
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
- LookupResult Operators;
- LookupName(Operators, S, OpName, LookupOperatorName);
+ LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName);
+ LookupName(Operators, S);
assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 3e6778bc4770..adcd977e626d 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "Lookup.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ASTContext.h"
@@ -350,7 +351,7 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD,
if (NewTemplate &&
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
- false, false, SourceLocation()) ||
+ false, TPL_TemplateMatch) ||
OldType->getResultType() != NewType->getResultType()))
return true;
@@ -519,8 +520,6 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// cv-unqualified version of T. Otherwise, the type of the rvalue
// is T (C++ 4.1p1). C++ can't get here with class types; in C, we
// just strip the qualifiers because they don't matter.
-
- // FIXME: Doesn't see through to qualifiers behind a typedef!
FromType = FromType.getUnqualifiedType();
} else if (FromType->isArrayType()) {
// Array-to-pointer conversion (C++ 4.2)
@@ -678,8 +677,9 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// a conversion. [...]
CanonFrom = Context.getCanonicalType(FromType);
CanonTo = Context.getCanonicalType(ToType);
- if (CanonFrom.getUnqualifiedType() == CanonTo.getUnqualifiedType() &&
- CanonFrom.getCVRQualifiers() != CanonTo.getCVRQualifiers()) {
+ if (CanonFrom.getLocalUnqualifiedType()
+ == CanonTo.getLocalUnqualifiedType() &&
+ CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()) {
FromType = ToType;
CanonFrom = CanonTo;
}
@@ -756,8 +756,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// We found the type that we can promote to. If this is the
// type we wanted, we have a promotion. Otherwise, no
// promotion.
- return Context.getCanonicalType(ToType).getUnqualifiedType()
- == Context.getCanonicalType(PromoteTypes[Idx]).getUnqualifiedType();
+ return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]);
}
}
}
@@ -864,7 +863,7 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
Qualifiers Quals = CanonFromPointee.getQualifiers();
// Exact qualifier match -> return the pointer type we're converting to.
- if (CanonToPointee.getQualifiers() == Quals) {
+ if (CanonToPointee.getLocalQualifiers() == Quals) {
// ToType is exactly what we need. Return it.
if (!ToType.isNull())
return ToType;
@@ -876,7 +875,8 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
// Just build a canonical type that has the right qualifiers.
return Context.getPointerType(
- Context.getQualifiedType(CanonToPointee.getUnqualifiedType(), Quals));
+ Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(),
+ Quals));
}
static bool isNullPointerConstantForConversion(Expr *Expr,
@@ -1155,7 +1155,8 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
/// true. It returns true and produces a diagnostic if there was an
/// error, or returns false otherwise.
bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
- CastExpr::CastKind &Kind) {
+ CastExpr::CastKind &Kind,
+ bool IgnoreBaseAccess) {
QualType FromType = From->getType();
if (const PointerType *FromPtrType = FromType->getAs<PointerType>())
@@ -1169,7 +1170,8 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
// ambiguous or inaccessible conversion.
if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType,
From->getExprLoc(),
- From->getSourceRange()))
+ From->getSourceRange(),
+ IgnoreBaseAccess))
return true;
// The conversion was successful.
@@ -1238,7 +1240,9 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
/// true and produces a diagnostic if there was an error, or returns false
/// otherwise.
bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
- CastExpr::CastKind &Kind) {
+ CastExpr::CastKind &Kind,
+ bool IgnoreBaseAccess) {
+ (void)IgnoreBaseAccess;
QualType FromType = From->getType();
const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
if (!FromPtrType) {
@@ -1344,8 +1348,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
// of types. If we unwrapped any pointers, and if FromType and
// ToType have the same unqualified type (since we checked
// qualifiers above), then this is a qualification conversion.
- return UnwrappedAnyPointer &&
- FromType.getUnqualifiedType() == ToType.getUnqualifiedType();
+ return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
}
/// \brief Given a function template or function, extract the function template
@@ -1399,6 +1402,13 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
// functions are all the converting constructors (12.3.1) of
// that class. The argument list is the expression-list within
// the parentheses of the initializer.
+ bool SuppressUserConversions = !UserCast;
+ if (Context.hasSameUnqualifiedType(ToType, From->getType()) ||
+ IsDerivedFrom(From->getType(), ToType)) {
+ SuppressUserConversions = false;
+ AllowConversionFunctions = false;
+ }
+
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ToType).getUnqualifiedType());
@@ -1415,20 +1425,18 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(*Con);
-
+
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, &From,
- 1, CandidateSet,
- /*SuppressUserConversions=*/!UserCast,
- ForceRValue);
+ 1, CandidateSet,
+ SuppressUserConversions, ForceRValue);
else
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
- /*SuppressUserConversions=*/!UserCast,
- ForceRValue);
+ SuppressUserConversions, ForceRValue);
}
}
}
@@ -1481,9 +1489,14 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
// sequence converts the source type to the type required by
// the argument of the constructor.
//
- // FIXME: What about ellipsis conversions?
QualType ThisType = Constructor->getThisType(Context);
- User.Before = Best->Conversions[0].Standard;
+ if (Best->Conversions[0].ConversionKind ==
+ ImplicitConversionSequence::EllipsisConversion)
+ User.EllipsisConversion = true;
+ else {
+ User.Before = Best->Conversions[0].Standard;
+ User.EllipsisConversion = false;
+ }
User.ConversionFunction = Constructor;
User.After.setAsIdentityConversion();
User.After.FromTypePtr
@@ -1500,6 +1513,7 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
// implicit object parameter of the conversion function.
User.Before = Best->Conversions[0].Standard;
User.ConversionFunction = Conversion;
+ User.EllipsisConversion = false;
// C++ [over.ics.user]p2:
// The second standard conversion sequence converts the
@@ -1727,7 +1741,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
- if (T1.getUnqualifiedType() == T2.getUnqualifiedType()) {
+ if (Context.hasSameUnqualifiedType(T1, T2)) {
if (T2.isMoreQualifiedThan(T1))
return ImplicitConversionSequence::Better;
else if (T1.isMoreQualifiedThan(T2))
@@ -1763,7 +1777,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
// If the types are the same, we won't learn anything by unwrapped
// them.
- if (T1.getUnqualifiedType() == T2.getUnqualifiedType())
+ if (Context.hasSameUnqualifiedType(T1, T2))
return ImplicitConversionSequence::Indistinguishable;
ImplicitConversionSequence::CompareKind Result
@@ -1803,7 +1817,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
}
// If the types after this point are equivalent, we're done.
- if (T1.getUnqualifiedType() == T2.getUnqualifiedType())
+ if (Context.hasSameUnqualifiedType(T1, T2))
break;
}
@@ -1918,8 +1932,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
// -- binding of an expression of type C to a reference of type
// B& is better than binding an expression of type C to a
// reference of type A&,
- if (FromType1.getUnqualifiedType() == FromType2.getUnqualifiedType() &&
- ToType1.getUnqualifiedType() != ToType2.getUnqualifiedType()) {
+ if (Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ !Context.hasSameUnqualifiedType(ToType1, ToType2)) {
if (IsDerivedFrom(ToType1, ToType2))
return ImplicitConversionSequence::Better;
else if (IsDerivedFrom(ToType2, ToType1))
@@ -1929,8 +1943,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
// -- binding of an expression of type B to a reference of type
// A& is better than binding an expression of type C to a
// reference of type A&,
- if (FromType1.getUnqualifiedType() != FromType2.getUnqualifiedType() &&
- ToType1.getUnqualifiedType() == ToType2.getUnqualifiedType()) {
+ if (!Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ Context.hasSameUnqualifiedType(ToType1, ToType2)) {
if (IsDerivedFrom(FromType2, FromType1))
return ImplicitConversionSequence::Better;
else if (IsDerivedFrom(FromType1, FromType2))
@@ -1977,8 +1991,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
if (SCS1.CopyConstructor && SCS2.CopyConstructor &&
SCS1.Second == ICK_Derived_To_Base) {
// -- conversion of C to B is better than conversion of C to A,
- if (FromType1.getUnqualifiedType() == FromType2.getUnqualifiedType() &&
- ToType1.getUnqualifiedType() != ToType2.getUnqualifiedType()) {
+ if (Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ !Context.hasSameUnqualifiedType(ToType1, ToType2)) {
if (IsDerivedFrom(ToType1, ToType2))
return ImplicitConversionSequence::Better;
else if (IsDerivedFrom(ToType2, ToType1))
@@ -1986,8 +2000,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
}
// -- conversion of B to A is better than conversion of C to A.
- if (FromType1.getUnqualifiedType() != FromType2.getUnqualifiedType() &&
- ToType1.getUnqualifiedType() == ToType2.getUnqualifiedType()) {
+ if (!Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ Context.hasSameUnqualifiedType(ToType1, ToType2)) {
if (IsDerivedFrom(FromType2, FromType1))
return ImplicitConversionSequence::Better;
else if (IsDerivedFrom(FromType1, FromType2))
@@ -2099,14 +2113,15 @@ Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
// First check the qualifiers. We don't care about lvalue-vs-rvalue
// with the implicit object parameter (C++ [over.match.funcs]p5).
QualType FromTypeCanon = Context.getCanonicalType(FromType);
- if (ImplicitParamType.getCVRQualifiers() != FromTypeCanon.getCVRQualifiers() &&
+ if (ImplicitParamType.getCVRQualifiers()
+ != FromTypeCanon.getLocalCVRQualifiers() &&
!ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon))
return ICS;
// Check that we have either the same type or a derived type. It
// affects the conversion rank.
QualType ClassTypeCanon = Context.getCanonicalType(ClassType);
- if (ClassTypeCanon == FromTypeCanon.getUnqualifiedType())
+ if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType())
ICS.Standard.Second = ICK_Identity;
else if (IsDerivedFrom(FromType, ClassType))
ICS.Standard.Second = ICK_Derived_To_Base;
@@ -2228,7 +2243,18 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
if (!CandidateSet.isNewCandidate(Function))
return;
-
+
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){
+ // C++ [class.copy]p3:
+ // A member function template is never instantiated to perform the copy
+ // of a class object to an object of its class type.
+ QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
+ if (NumArgs == 1 &&
+ Constructor->isCopyConstructorLikeSpecialization() &&
+ Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()))
+ return;
+ }
+
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
@@ -2342,6 +2368,33 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
}
}
+/// AddMethodCandidate - Adds a named decl (which is some kind of
+/// method) as a method candidate to the given overload set.
+void Sema::AddMethodCandidate(NamedDecl *Decl, Expr *Object,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions, bool ForceRValue) {
+
+ // FIXME: use this
+ //DeclContext *ActingContext = Decl->getDeclContext();
+
+ if (isa<UsingShadowDecl>(Decl))
+ Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
+
+ if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
+ assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
+ "Expected a member function template");
+ AddMethodTemplateCandidate(TD, false, 0, 0,
+ Object, Args, NumArgs,
+ CandidateSet,
+ SuppressUserConversions,
+ ForceRValue);
+ } else {
+ AddMethodCandidate(cast<CXXMethodDecl>(Decl), Object, Args, NumArgs,
+ CandidateSet, SuppressUserConversions, ForceRValue);
+ }
+}
+
/// AddMethodCandidate - Adds the given C++ member function to the set
/// of candidate functions, using the given function call arguments
/// and the object argument (@c Object). For example, in a call
@@ -2593,7 +2646,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// call on the stack and we don't need its arguments to be
// well-formed.
DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
- SourceLocation());
+ From->getLocStart());
ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()),
CastExpr::CK_FunctionToPointerDecay,
&ConversionRef, false);
@@ -2603,7 +2656,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// allocator).
CallExpr Call(Context, &ConversionFn, 0, 0,
Conversion->getConversionType().getNonReferenceType(),
- SourceLocation());
+ From->getLocStart());
ImplicitConversionSequence ICS =
TryCopyInitialization(&Call, ToType,
/*SuppressUserConversions=*/true,
@@ -2693,6 +2746,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Candidate.Conversions[0].ConversionKind
= ImplicitConversionSequence::UserDefinedConversion;
Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
+ Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
Candidate.Conversions[0].UserDefined.After
= Candidate.Conversions[0].UserDefined.Before;
@@ -2807,27 +2861,16 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
if (RequireCompleteType(OpLoc, T1, PDiag()))
return;
- LookupResult Operators;
- LookupQualifiedName(Operators, T1Rec->getDecl(), OpName,
- LookupOrdinaryName, false);
+ LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName);
+ LookupQualifiedName(Operators, T1Rec->getDecl());
+ Operators.suppressDiagnostics();
+
for (LookupResult::iterator Oper = Operators.begin(),
OperEnd = Operators.end();
Oper != OperEnd;
- ++Oper) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Oper)) {
- AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
- /*SuppressUserConversions=*/false);
- continue;
- }
-
- assert(isa<FunctionTemplateDecl>(*Oper) &&
- isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(*Oper)
- ->getTemplatedDecl()) &&
- "Expected a member function template");
- AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Oper), false, 0, 0,
- Args[0], Args+1, NumArgs - 1, CandidateSet,
- /*SuppressUserConversions=*/false);
- }
+ ++Oper)
+ AddMethodCandidate(*Oper, Args[0], Args + 1, NumArgs - 1, CandidateSet,
+ /* SuppressUserConversions = */ false);
}
}
@@ -2975,6 +3018,8 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
QualType PointeeTy = PointerTy->getPointeeType();
unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+ if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy))
+ BaseCVR = Array->getElementType().getCVRQualifiers();
bool hasVolatile = VisibleQuals.hasVolatile();
bool hasRestrict = VisibleQuals.hasRestrict();
@@ -3050,7 +3095,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
Ty = RefTy->getPointeeType();
// We don't care about qualifiers on the type.
- Ty = Ty.getUnqualifiedType();
+ Ty = Ty.getLocalUnqualifiedType();
// If we're dealing with an array type, decay to the pointer.
if (Ty->isArrayType())
@@ -4710,10 +4755,10 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
UsualUnaryConversions(FnExpr);
input.release();
-
+ Args[0] = Input;
ExprOwningPtr<CallExpr> TheCall(this,
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
- &Input, 1, ResultTy, OpLoc));
+ Args, NumArgs, ResultTy, OpLoc));
if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(),
FnDecl))
@@ -5226,17 +5271,22 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// (E).operator().
OverloadCandidateSet CandidateSet;
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
- DeclContext::lookup_const_iterator Oper, OperEnd;
- for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(OpName);
- Oper != OperEnd; ++Oper)
- AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
- CandidateSet, /*SuppressUserConversions=*/false);
if (RequireCompleteType(LParenLoc, Object->getType(),
PartialDiagnostic(diag::err_incomplete_object_call)
- << Object->getSourceRange()))
+ << Object->getSourceRange()))
return true;
+ LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
+ LookupQualifiedName(R, Record->getDecl());
+ R.suppressDiagnostics();
+
+ for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
+ Oper != OperEnd; ++Oper) {
+ AddMethodCandidate(*Oper, Object, Args, NumArgs, CandidateSet,
+ /*SuppressUserConversions=*/ false);
+ }
+
// C++ [over.call.object]p2:
// In addition, for each conversion function declared in T of the
// form
@@ -5405,7 +5455,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
QualType ProtoArgType = Proto->getArgType(i);
IsError |= PerformCopyInitialization(Arg, ProtoArgType, "passing");
} else {
- Arg = CXXDefaultArgExpr::Create(Context, Method->getParamDecl(i));
+ OwningExprResult DefArg
+ = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
+ if (DefArg.isInvalid()) {
+ IsError = true;
+ break;
+ }
+
+ Arg = DefArg.takeAs<Expr>();
}
TheCall->setArg(i + 1, Arg);
@@ -5447,8 +5504,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
OverloadCandidateSet CandidateSet;
const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
- LookupResult R;
- LookupQualifiedName(R, BaseRecord->getDecl(), OpName, LookupOrdinaryName);
+ if (RequireCompleteType(Base->getLocStart(), Base->getType(),
+ PDiag(diag::err_typecheck_incomplete_tag)
+ << Base->getSourceRange()))
+ return ExprError();
+
+ LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
+ LookupQualifiedName(R, BaseRecord->getDecl());
+ R.suppressDiagnostics();
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper)
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
index 898393a9e4d9..0d1f37aa4beb 100644
--- a/lib/Sema/SemaOverload.h
+++ b/lib/Sema/SemaOverload.h
@@ -156,6 +156,14 @@ namespace clang {
/// object parameter of the conversion function.
StandardConversionSequence Before;
+ /// EllipsisConversion - When this is true, it means user-defined
+ /// conversion sequence starts with a ... (elipsis) conversion, instead of
+ /// a standard conversion. In this case, 'Before' field must be ignored.
+ // FIXME. I much rather put this as the first field. But there seems to be
+ // a gcc code gen. bug which causes a crash in a test. Putting it here seems
+ // to work around the crash.
+ bool EllipsisConversion : 1;
+
/// After - Represents the standard conversion that occurs after
/// the actual user-defined conversion.
StandardConversionSequence After;
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 6a65bd1dd1ec..d0f214fbd83d 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -873,8 +873,7 @@ static bool IsReturnCopyElidable(ASTContext &Ctx, QualType RetType,
if (!RetType->isRecordType())
return false;
// ... the same cv-unqualified type as the function return type ...
- if (Ctx.getCanonicalType(RetType).getUnqualifiedType() !=
- Ctx.getCanonicalType(ExprType).getUnqualifiedType())
+ if (!Ctx.hasSameUnqualifiedType(RetType, ExprType))
return false;
// ... the expression is the name of a non-volatile automatic object ...
// We ignore parentheses here.
@@ -965,9 +964,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
// FIXME: Leaks RetValExp on error.
- if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable))
+ if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable)){
+ // We should still clean up our temporaries, even when we're failing!
+ RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true);
return StmtError();
-
+ }
+
if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5ef370104dd9..466a0e37d49c 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -10,12 +10,14 @@
//===----------------------------------------------------------------------===/
#include "Sema.h"
+#include "Lookup.h"
#include "TreeTransform.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/Support/Compiler.h"
@@ -129,29 +131,29 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
LookupCtx = computeDeclContext(ObjectType);
isDependent = ObjectType->isDependentType();
+ assert((isDependent || !ObjectType->isIncompleteType()) &&
+ "Caller should have completed object type");
} else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
-
LookupCtx = computeDeclContext(SS, EnteringContext);
isDependent = isDependentScopeSpecifier(SS);
+
+ // The declaration context must be complete.
+ if (LookupCtx && RequireCompleteDeclContext(SS))
+ return TNK_Non_template;
}
- LookupResult Found;
+ LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName);
bool ObjectTypeSearchedInScope = false;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
// computed, which is either the type of the base of a member access
// expression or the declaration context associated with a prior
// nested-name-specifier.
+ LookupQualifiedName(Found, LookupCtx);
- // The declaration context must be complete.
- if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS))
- return TNK_Non_template;
-
- LookupQualifiedName(Found, LookupCtx, TName, LookupOrdinaryName);
-
- if (ObjectTypePtr && Found.getKind() == LookupResult::NotFound) {
+ if (ObjectTypePtr && Found.empty()) {
// C++ [basic.lookup.classref]p1:
// In a class member access expression (5.2.5), if the . or -> token is
// immediately followed by an identifier followed by a <, the
@@ -164,7 +166,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
//
// FIXME: When we're instantiating a template, do we actually have to
// look in the scope of the template? Seems fishy...
- LookupName(Found, S, TName, LookupOrdinaryName);
+ LookupName(Found, S);
ObjectTypeSearchedInScope = true;
}
} else if (isDependent) {
@@ -172,7 +174,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
return TNK_Non_template;
} else {
// Perform unqualified name lookup in the current scope.
- LookupName(Found, S, TName, LookupOrdinaryName);
+ LookupName(Found, S);
}
// FIXME: Cope with ambiguous name-lookup results.
@@ -190,8 +192,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// template, the name is also looked up in the context of the entire
// postfix-expression and [...]
//
- LookupResult FoundOuter;
- LookupName(FoundOuter, S, TName, LookupOrdinaryName);
+ LookupResult FoundOuter(*this, TName, SourceLocation(), LookupOrdinaryName);
+ LookupName(FoundOuter, S);
// FIXME: Handle ambiguities in this lookup better
NamedDecl *OuterTemplate
= isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context));
@@ -283,6 +285,46 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) {
return 0;
}
+static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
+ const ParsedTemplateArgument &Arg) {
+
+ switch (Arg.getKind()) {
+ case ParsedTemplateArgument::Type: {
+ DeclaratorInfo *DI;
+ QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
+ if (!DI)
+ DI = SemaRef.Context.getTrivialDeclaratorInfo(T, Arg.getLocation());
+ return TemplateArgumentLoc(TemplateArgument(T), DI);
+ }
+
+ case ParsedTemplateArgument::NonType: {
+ Expr *E = static_cast<Expr *>(Arg.getAsExpr());
+ return TemplateArgumentLoc(TemplateArgument(E), E);
+ }
+
+ case ParsedTemplateArgument::Template: {
+ TemplateName Template
+ = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get());
+ return TemplateArgumentLoc(TemplateArgument(Template),
+ Arg.getScopeSpec().getRange(),
+ Arg.getLocation());
+ }
+ }
+
+ llvm::llvm_unreachable("Unhandled parsed template argument");
+ return TemplateArgumentLoc();
+}
+
+/// \brief Translates template arguments as provided by the parser
+/// into template arguments used by semantic analysis.
+void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
+ llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
+ TemplateArgs.reserve(TemplateArgsIn.size());
+
+ for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
+ TemplateArgs.push_back(translateTemplateArgument(*this, TemplateArgsIn[I]));
+}
+
/// ActOnTypeParameter - Called when a C++ template type parameter
/// (e.g., "typename T") has been parsed. Typename specifies whether
/// the keyword "typename" was used to declare the type parameter
@@ -517,34 +559,30 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
/// parameter.
void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
SourceLocation EqualLoc,
- ExprArg DefaultE) {
+ const ParsedTemplateArgument &Default) {
TemplateTemplateParmDecl *TemplateParm
= cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
-
- // Since a template-template parameter's default argument is an
- // id-expression, it must be a DeclRefExpr.
- DeclRefExpr *Default
- = cast<DeclRefExpr>(static_cast<Expr *>(DefaultE.get()));
-
+
// C++ [temp.param]p14:
// A template-parameter shall not be used in its own default argument.
// FIXME: Implement this check! Needs a recursive walk over the types.
- // Check the well-formedness of the template argument.
- if (!isa<TemplateDecl>(Default->getDecl())) {
- Diag(Default->getSourceRange().getBegin(),
- diag::err_template_arg_must_be_template)
- << Default->getSourceRange();
- TemplateParm->setInvalidDecl();
- return;
- }
- if (CheckTemplateArgument(TemplateParm, Default)) {
- TemplateParm->setInvalidDecl();
+ // Check only that we have a template template argument. We don't want to
+ // try to check well-formedness now, because our template template parameter
+ // might have dependent types in its template parameters, which we wouldn't
+ // be able to match now.
+ //
+ // If none of the template template parameter's template arguments mention
+ // other template parameters, we could actually perform more checking here.
+ // However, it isn't worth doing.
+ TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+ if (DefaultArg.getArgument().getAsTemplate().isNull()) {
+ Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
+ << DefaultArg.getSourceRange();
return;
}
-
- DefaultE.release();
- TemplateParm->setDefaultArgument(Default);
+
+ TemplateParm->setDefaultArgument(DefaultArg);
}
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
@@ -591,7 +629,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Find any previous declaration with this name.
DeclContext *SemanticContext;
- LookupResult Previous;
+ LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
+ ForRedeclaration);
if (SS.isNotEmpty() && !SS.isInvalid()) {
if (RequireCompleteDeclContext(SS))
return true;
@@ -602,11 +641,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
return true;
}
- LookupQualifiedName(Previous, SemanticContext, Name, LookupOrdinaryName,
- true);
+ LookupQualifiedName(Previous, SemanticContext);
} else {
SemanticContext = CurContext;
- LookupName(Previous, S, Name, LookupOrdinaryName, true);
+ LookupName(Previous, S);
}
assert(!Previous.isAmbiguous() && "Ambiguity in class template redecl?");
@@ -669,7 +707,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Ensure that the template parameter lists are compatible.
if (!TemplateParameterListsAreEqual(TemplateParams,
PrevClassTemplate->getTemplateParameters(),
- /*Complain=*/true))
+ /*Complain=*/true,
+ TPL_TemplateMatch))
return true;
// C++ [temp.class]p4:
@@ -923,8 +962,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
= OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
NewTemplateParm->hasDefaultArgument()) {
- OldDefaultLoc = OldTemplateParm->getDefaultArgumentLoc();
- NewDefaultLoc = NewTemplateParm->getDefaultArgumentLoc();
+ OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
+ NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
SawDefaultArgument = true;
RedundantDefaultArg = true;
PreviousDefaultArgLoc = NewDefaultLoc;
@@ -936,10 +975,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// that points to a previous template template parameter.
NewTemplateParm->setDefaultArgument(
OldTemplateParm->getDefaultArgument());
- PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgumentLoc();
+ PreviousDefaultArgLoc
+ = OldTemplateParm->getDefaultArgument().getLocation();
} else if (NewTemplateParm->hasDefaultArgument()) {
SawDefaultArgument = true;
- PreviousDefaultArgLoc = NewTemplateParm->getDefaultArgumentLoc();
+ PreviousDefaultArgLoc
+ = NewTemplateParm->getDefaultArgument().getLocation();
} else if (SawDefaultArgument)
MissingDefaultArg = true;
}
@@ -1085,7 +1126,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
if (ExpectedTemplateParams)
TemplateParameterListsAreEqual(ParamLists[Idx],
ExpectedTemplateParams,
- true);
+ true, TPL_TemplateMatch);
}
} else if (ParamLists[Idx]->size() > 0)
Diag(ParamLists[Idx]->getTemplateLoc(),
@@ -1118,28 +1159,6 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
return ParamLists[NumParamLists - 1];
}
-/// \brief Translates template arguments as provided by the parser
-/// into template arguments used by semantic analysis.
-void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
- llvm::SmallVector<TemplateArgumentLoc, 16> &TemplateArgs) {
- TemplateArgs.reserve(TemplateArgsIn.size());
-
- void **Args = TemplateArgsIn.getArgs();
- bool *ArgIsType = TemplateArgsIn.getArgIsType();
- for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) {
- if (ArgIsType[Arg]) {
- DeclaratorInfo *DI;
- QualType T = Sema::GetTypeFromParser(Args[Arg], &DI);
- if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]);
- TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI));
- } else {
- Expr *E = reinterpret_cast<Expr *>(Args[Arg]);
- TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
- }
- }
-}
-
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
@@ -1169,7 +1188,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
QualType CanonType;
- if (TemplateSpecializationType::anyDependentTemplateArguments(
+ if (Name.isDependent() ||
+ TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs,
NumTemplateArgs)) {
// This class template specialization is a dependent
@@ -1228,13 +1248,12 @@ Action::TypeResult
Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocsIn,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
TemplateArgs.data(),
@@ -1336,13 +1355,12 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgSLs,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
TemplateArgsIn.release();
return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
@@ -1449,6 +1467,333 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
return false;
}
+/// \brief Substitute template arguments into the default template argument for
+/// the given template type parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static DeclaratorInfo *
+SubstDefaultTemplateArgument(Sema &SemaRef,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateTypeParmDecl *Param,
+ TemplateArgumentListBuilder &Converted) {
+ DeclaratorInfo *ArgType = Param->getDefaultArgumentInfo();
+
+ // If the argument type is dependent, instantiate it now based
+ // on the previously-computed template arguments.
+ if (ArgType->getType()->isDependentType()) {
+ TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+ /*TakeArgs=*/false);
+
+ MultiLevelTemplateArgumentList AllTemplateArgs
+ = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+ Template, Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
+ Param->getDefaultArgumentLoc(),
+ Param->getDeclName());
+ }
+
+ return ArgType;
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given non-type template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the non-type template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static Sema::OwningExprResult
+SubstDefaultTemplateArgument(Sema &SemaRef,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ NonTypeTemplateParmDecl *Param,
+ TemplateArgumentListBuilder &Converted) {
+ TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+ /*TakeArgs=*/false);
+
+ MultiLevelTemplateArgumentList AllTemplateArgs
+ = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+ Template, Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given template template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TemplateName
+SubstDefaultTemplateArgument(Sema &SemaRef,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateTemplateParmDecl *Param,
+ TemplateArgumentListBuilder &Converted) {
+ TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+ /*TakeArgs=*/false);
+
+ MultiLevelTemplateArgumentList AllTemplateArgs
+ = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+ Template, Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ return SemaRef.SubstTemplateName(
+ Param->getDefaultArgument().getArgument().getAsTemplate(),
+ Param->getDefaultArgument().getTemplateNameLoc(),
+ AllTemplateArgs);
+}
+
+/// \brief Check that the given template argument corresponds to the given
+/// template parameter.
+bool Sema::CheckTemplateArgument(NamedDecl *Param,
+ const TemplateArgumentLoc &Arg,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateArgumentListBuilder &Converted) {
+ // Check template type parameters.
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ return CheckTemplateTypeArgument(TTP, Arg, Converted);
+
+ // Check non-type template parameters.
+ if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ // Do substitution on the type of the non-type template parameter
+ // with the template arguments we've seen thus far.
+ QualType NTTPType = NTTP->getType();
+ if (NTTPType->isDependentType()) {
+ // Do substitution on the type of the non-type template parameter.
+ InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+ NTTP, Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ TemplateArgumentList TemplateArgs(Context, Converted,
+ /*TakeArgs=*/false);
+ NTTPType = SubstType(NTTPType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ // If that worked, check the non-type template parameter type
+ // for validity.
+ if (!NTTPType.isNull())
+ NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
+ NTTP->getLocation());
+ if (NTTPType.isNull())
+ return true;
+ }
+
+ switch (Arg.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Should never see a NULL template argument here");
+ return true;
+
+ case TemplateArgument::Expression: {
+ Expr *E = Arg.getArgument().getAsExpr();
+ TemplateArgument Result;
+ if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+ return true;
+
+ Converted.Append(Result);
+ break;
+ }
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ // We've already checked this template argument, so just copy
+ // it to the list of converted arguments.
+ Converted.Append(Arg.getArgument());
+ break;
+
+ case TemplateArgument::Template:
+ // We were given a template template argument. It may not be ill-formed;
+ // see below.
+ if (DependentTemplateName *DTN
+ = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+ // We have a template argument such as \c T::template X, which we
+ // parsed as a template template argument. However, since we now
+ // know that we need a non-type template argument, convert this
+ // template name into an expression.
+ Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(),
+ Context.DependentTy,
+ Arg.getTemplateNameLoc(),
+ Arg.getTemplateQualifierRange(),
+ DTN->getQualifier(),
+ /*isAddressOfOperand=*/false);
+
+ TemplateArgument Result;
+ if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+ return true;
+
+ Converted.Append(Result);
+ break;
+ }
+
+ // We have a template argument that actually does refer to a class
+ // template, template alias, or template template parameter, and
+ // therefore cannot be a non-type template argument.
+ Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
+ << Arg.getSourceRange();
+
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+
+ case TemplateArgument::Type: {
+ // We have a non-type template parameter but the template
+ // argument is a type.
+
+ // C++ [temp.arg]p2:
+ // In a template-argument, an ambiguity between a type-id and
+ // an expression is resolved to a type-id, regardless of the
+ // form of the corresponding template-parameter.
+ //
+ // We warn specifically about this case, since it can be rather
+ // confusing for users.
+ QualType T = Arg.getArgument().getAsType();
+ SourceRange SR = Arg.getSourceRange();
+ if (T->isFunctionType())
+ Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
+ else
+ Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ case TemplateArgument::Pack:
+ llvm::llvm_unreachable("Caller must expand template argument packs");
+ break;
+ }
+
+ return false;
+ }
+
+
+ // Check template template parameters.
+ TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+
+ // Substitute into the template parameter list of the template
+ // template parameter, since previously-supplied template arguments
+ // may appear within the template template parameter.
+ {
+ // Set up a template instantiation context.
+ LocalInstantiationScope Scope(*this);
+ InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+ TempParm, Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ TemplateArgumentList TemplateArgs(Context, Converted,
+ /*TakeArgs=*/false);
+ TempParm = cast_or_null<TemplateTemplateParmDecl>(
+ SubstDecl(TempParm, CurContext,
+ MultiLevelTemplateArgumentList(TemplateArgs)));
+ if (!TempParm)
+ return true;
+
+ // FIXME: TempParam is leaked.
+ }
+
+ switch (Arg.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Should never see a NULL template argument here");
+ return true;
+
+ case TemplateArgument::Template:
+ if (CheckTemplateArgument(TempParm, Arg))
+ return true;
+
+ Converted.Append(Arg.getArgument());
+ break;
+
+ case TemplateArgument::Expression:
+ case TemplateArgument::Type:
+ // We have a template template parameter but the template
+ // argument does not refer to a template.
+ Diag(Arg.getLocation(), diag::err_template_arg_must_be_template);
+ return true;
+
+ case TemplateArgument::Declaration:
+ llvm::llvm_unreachable(
+ "Declaration argument with template template parameter");
+ break;
+ case TemplateArgument::Integral:
+ llvm::llvm_unreachable(
+ "Integral argument with template template parameter");
+ break;
+
+ case TemplateArgument::Pack:
+ llvm::llvm_unreachable("Caller must expand template argument packs");
+ break;
+ }
+
+ return false;
+}
+
/// \brief Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
@@ -1499,226 +1844,105 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (ArgIdx > NumArgs && PartialTemplateArgs)
break;
- // Decode the template argument
- TemplateArgumentLoc Arg;
-
- if (ArgIdx >= NumArgs) {
- // Retrieve the default template argument from the template
- // parameter.
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
- if (TTP->isParameterPack()) {
- // We have an empty argument pack.
- Converted.BeginPack();
- Converted.EndPack();
- break;
- }
-
- if (!TTP->hasDefaultArgument())
+ // If we have a template parameter pack, check every remaining template
+ // argument against that template parameter pack.
+ if ((*Param)->isTemplateParameterPack()) {
+ Converted.BeginPack();
+ for (; ArgIdx < NumArgs; ++ArgIdx) {
+ if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
+ TemplateLoc, RAngleLoc, Converted)) {
+ Invalid = true;
break;
-
- DeclaratorInfo *ArgType = TTP->getDefaultArgumentInfo();
-
- // If the argument type is dependent, instantiate it now based
- // on the previously-computed template arguments.
- if (ArgType->getType()->isDependentType()) {
- InstantiatingTemplate Inst(*this, TemplateLoc,
- Template, Converted.getFlatArguments(),
- Converted.flatSize(),
- SourceRange(TemplateLoc, RAngleLoc));
-
- TemplateArgumentList TemplateArgs(Context, Converted,
- /*TakeArgs=*/false);
- ArgType = SubstType(ArgType,
- MultiLevelTemplateArgumentList(TemplateArgs),
- TTP->getDefaultArgumentLoc(),
- TTP->getDeclName());
}
-
- if (!ArgType)
- return true;
-
- Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), ArgType);
- } else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
- if (!NTTP->hasDefaultArgument())
- break;
-
- InstantiatingTemplate Inst(*this, TemplateLoc,
- Template, Converted.getFlatArguments(),
- Converted.flatSize(),
- SourceRange(TemplateLoc, RAngleLoc));
-
- TemplateArgumentList TemplateArgs(Context, Converted,
- /*TakeArgs=*/false);
-
- Sema::OwningExprResult E
- = SubstExpr(NTTP->getDefaultArgument(),
- MultiLevelTemplateArgumentList(TemplateArgs));
- if (E.isInvalid())
- return true;
-
- Expr *Ex = E.takeAs<Expr>();
- Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
- } else {
- TemplateTemplateParmDecl *TempParm
- = cast<TemplateTemplateParmDecl>(*Param);
-
- if (!TempParm->hasDefaultArgument())
- break;
-
- // FIXME: Subst default argument
- Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()),
- TempParm->getDefaultArgument());
}
- } else {
- // Retrieve the template argument produced by the user.
- Arg = TemplateArgs[ArgIdx];
+ Converted.EndPack();
+ continue;
}
-
-
+
+ if (ArgIdx < NumArgs) {
+ // Check the template argument we were given.
+ if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
+ TemplateLoc, RAngleLoc, Converted))
+ return true;
+
+ continue;
+ }
+
+ // We have a default template argument that we will use.
+ TemplateArgumentLoc Arg;
+
+ // Retrieve the default template argument from the template
+ // parameter. For each kind of template parameter, we substitute the
+ // template arguments provided thus far and any "outer" template arguments
+ // (when the template parameter was part of a nested template) into
+ // the default argument.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
- if (TTP->isParameterPack()) {
- Converted.BeginPack();
- // Check all the remaining arguments (if any).
- for (; ArgIdx < NumArgs; ++ArgIdx) {
- if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted))
- Invalid = true;
- }
-
- Converted.EndPack();
- } else {
- if (CheckTemplateTypeArgument(TTP, Arg, Converted))
- Invalid = true;
+ if (!TTP->hasDefaultArgument()) {
+ assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+ break;
}
+
+ DeclaratorInfo *ArgType = SubstDefaultTemplateArgument(*this,
+ Template,
+ TemplateLoc,
+ RAngleLoc,
+ TTP,
+ Converted);
+ if (!ArgType)
+ return true;
+
+ Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()),
+ ArgType);
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
- // Check non-type template parameters.
-
- // Do substitution on the type of the non-type template parameter
- // with the template arguments we've seen thus far.
- QualType NTTPType = NTTP->getType();
- if (NTTPType->isDependentType()) {
- // Do substitution on the type of the non-type template parameter.
- InstantiatingTemplate Inst(*this, TemplateLoc,
- Template, Converted.getFlatArguments(),
- Converted.flatSize(),
- SourceRange(TemplateLoc, RAngleLoc));
-
- TemplateArgumentList TemplateArgs(Context, Converted,
- /*TakeArgs=*/false);
- NTTPType = SubstType(NTTPType,
- MultiLevelTemplateArgumentList(TemplateArgs),
- NTTP->getLocation(),
- NTTP->getDeclName());
- // If that worked, check the non-type template parameter type
- // for validity.
- if (!NTTPType.isNull())
- NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
- NTTP->getLocation());
- if (NTTPType.isNull()) {
- Invalid = true;
- break;
- }
- }
-
- switch (Arg.getArgument().getKind()) {
- case TemplateArgument::Null:
- assert(false && "Should never see a NULL template argument here");
- break;
-
- case TemplateArgument::Expression: {
- Expr *E = Arg.getArgument().getAsExpr();
- TemplateArgument Result;
- if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
- Invalid = true;
- else
- Converted.Append(Result);
+ if (!NTTP->hasDefaultArgument()) {
+ assert((Invalid || PartialTemplateArgs) && "Missing default argument");
break;
}
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- // We've already checked this template argument, so just copy
- // it to the list of converted arguments.
- Converted.Append(Arg.getArgument());
- break;
-
- case TemplateArgument::Type: {
- // We have a non-type template parameter but the template
- // argument is a type.
-
- // C++ [temp.arg]p2:
- // In a template-argument, an ambiguity between a type-id and
- // an expression is resolved to a type-id, regardless of the
- // form of the corresponding template-parameter.
- //
- // We warn specifically about this case, since it can be rather
- // confusing for users.
- QualType T = Arg.getArgument().getAsType();
- SourceRange SR = Arg.getSourceRange();
- if (T->isFunctionType())
- Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig)
- << SR << T;
- else
- Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
- Diag((*Param)->getLocation(), diag::note_template_param_here);
- Invalid = true;
- break;
- }
+ Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ NTTP,
+ Converted);
+ if (E.isInvalid())
+ return true;
- case TemplateArgument::Pack:
- assert(0 && "FIXME: Implement!");
- break;
- }
+ Expr *Ex = E.takeAs<Expr>();
+ Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
} else {
- // Check template template parameters.
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
- switch (Arg.getArgument().getKind()) {
- case TemplateArgument::Null:
- assert(false && "Should never see a NULL template argument here");
+ if (!TempParm->hasDefaultArgument()) {
+ assert((Invalid || PartialTemplateArgs) && "Missing default argument");
break;
-
- case TemplateArgument::Expression: {
- Expr *ArgExpr = Arg.getArgument().getAsExpr();
- if (ArgExpr && isa<DeclRefExpr>(ArgExpr) &&
- isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) {
- if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
- Invalid = true;
-
- // Add the converted template argument.
- Decl *D
- = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl();
- Converted.Append(TemplateArgument(D));
- continue;
- }
}
- // fall through
- case TemplateArgument::Type: {
- // We have a template template parameter but the template
- // argument does not refer to a template.
- Diag(Arg.getLocation(), diag::err_template_arg_must_be_template);
- Invalid = true;
- break;
- }
-
- case TemplateArgument::Declaration:
- // We've already checked this template argument, so just copy
- // it to the list of converted arguments.
- Converted.Append(Arg.getArgument());
- break;
-
- case TemplateArgument::Integral:
- assert(false && "Integral argument with template template parameter");
- break;
-
- case TemplateArgument::Pack:
- assert(0 && "FIXME: Implement!");
- break;
- }
+ TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ TempParm,
+ Converted);
+ if (Name.isNull())
+ return true;
+
+ Arg = TemplateArgumentLoc(TemplateArgument(Name),
+ TempParm->getDefaultArgument().getTemplateQualifierRange(),
+ TempParm->getDefaultArgument().getTemplateNameLoc());
}
+
+ // Introduce an instantiation record that describes where we are using
+ // the default template argument.
+ InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param,
+ Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ // Check the default template argument.
+ if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
+ RAngleLoc, Converted))
+ return true;
}
return Invalid;
@@ -1864,8 +2088,8 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
/// \brief Checks whether the given template argument is a pointer to
/// member constant according to C++ [temp.arg.nontype]p1.
-bool
-Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
+bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
+ TemplateArgument &Converted) {
bool Invalid = false;
// See through any implicit casts we added to fix the type.
@@ -1896,13 +2120,33 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
Arg = Parens->getSubExpr();
}
- if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg))
+ // A pointer-to-member constant written &Class::member.
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
if (UnOp->getOpcode() == UnaryOperator::AddrOf) {
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
if (DRE && !DRE->getQualifier())
DRE = 0;
}
-
+ }
+ // A constant of pointer-to-member type.
+ else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
+ if (VD->getType()->isMemberPointerType()) {
+ if (isa<NonTypeTemplateParmDecl>(VD) ||
+ (isa<VarDecl>(VD) &&
+ Context.getCanonicalType(VD->getType()).isConstQualified())) {
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ Converted = TemplateArgument(Arg->Retain());
+ else
+ Converted = TemplateArgument(VD->getCanonicalDecl());
+ return Invalid;
+ }
+ }
+ }
+
+ DRE = 0;
+ }
+
if (!DRE)
return Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_not_pointer_to_member_form)
@@ -1915,7 +2159,10 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
// Okay: this is the address of a non-static member, and therefore
// a member pointer constant.
- Member = DRE->getDecl();
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ Converted = TemplateArgument(Arg->Retain());
+ else
+ Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl());
return Invalid;
}
@@ -2119,16 +2366,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return true;
}
- if (ParamType->isMemberPointerType()) {
- NamedDecl *Member = 0;
- if (CheckTemplateArgumentPointerToMember(Arg, Member))
- return true;
-
- if (Member)
- Member = cast<NamedDecl>(Member->getCanonicalDecl());
- Converted = TemplateArgument(Member);
- return false;
- }
+ if (ParamType->isMemberPointerType())
+ return CheckTemplateArgumentPointerToMember(Arg, Converted);
NamedDecl *Entity = 0;
if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
@@ -2241,14 +2480,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return true;
}
- NamedDecl *Member = 0;
- if (CheckTemplateArgumentPointerToMember(Arg, Member))
- return true;
-
- if (Member)
- Member = cast<NamedDecl>(Member->getCanonicalDecl());
- Converted = TemplateArgument(Member);
- return false;
+ return CheckTemplateArgumentPointerToMember(Arg, Converted);
}
/// \brief Check a template argument against its corresponding
@@ -2257,9 +2489,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
/// This routine implements the semantics of C++ [temp.arg.template].
/// It returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- DeclRefExpr *Arg) {
- assert(isa<TemplateDecl>(Arg->getDecl()) && "Only template decls allowed");
- TemplateDecl *Template = cast<TemplateDecl>(Arg->getDecl());
+ const TemplateArgumentLoc &Arg) {
+ TemplateName Name = Arg.getArgument().getAsTemplate();
+ TemplateDecl *Template = Name.getAsTemplateDecl();
+ if (!Template) {
+ // Any dependent template name is fine.
+ assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
+ return false;
+ }
// C++ [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be
@@ -2276,15 +2513,16 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
!isa<TemplateTemplateParmDecl>(Template)) {
assert(isa<FunctionTemplateDecl>(Template) &&
"Only function templates are possible here");
- Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template);
+ Diag(Arg.getLocation(), diag::err_template_arg_not_class_template);
Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
<< Template;
}
return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Param->getTemplateParameters(),
- true, true,
- Arg->getSourceRange().getBegin());
+ true,
+ TPL_TemplateTemplateArgumentMatch,
+ Arg.getLocation());
}
/// \brief Determine whether the given template parameter lists are
@@ -2300,9 +2538,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
/// \param Complain If true, this routine will produce a diagnostic if
/// the template parameter lists are not equivalent.
///
-/// \param IsTemplateTemplateParm If true, this routine is being
-/// called to compare the template parameter lists of a template
-/// template parameter.
+/// \param Kind describes how we are to match the template parameter lists.
///
/// \param TemplateArgLoc If this source location is valid, then we
/// are actually checking the template parameter list of a template
@@ -2316,7 +2552,7 @@ bool
Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
- bool IsTemplateTemplateParm,
+ TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc) {
if (Old->size() != New->size()) {
if (Complain) {
@@ -2327,10 +2563,10 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
}
Diag(New->getTemplateLoc(), NextDiag)
<< (New->size() > Old->size())
- << IsTemplateTemplateParm
+ << (Kind != TPL_TemplateMatch)
<< SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
- << IsTemplateTemplateParm
+ << (Kind != TPL_TemplateMatch)
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
}
@@ -2348,9 +2584,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
NextDiag = diag::note_template_param_different_kind;
}
Diag((*NewParm)->getLocation(), NextDiag)
- << IsTemplateTemplateParm;
+ << (Kind != TPL_TemplateMatch);
Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
- << IsTemplateTemplateParm;
+ << (Kind != TPL_TemplateMatch);
}
return false;
}
@@ -2358,26 +2594,21 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
if (isa<TemplateTypeParmDecl>(*OldParm)) {
// Okay; all template type parameters are equivalent (since we
// know we're at the same index).
-#if 0
- // FIXME: Enable this code in debug mode *after* we properly go through
- // and "instantiate" the template parameter lists of template template
- // parameters. It's only after this instantiation that (1) any dependent
- // types within the template parameter list of the template template
- // parameter can be checked, and (2) the template type parameter depths
- // will match up.
- QualType OldParmType
- = Context.getTypeDeclType(cast<TemplateTypeParmDecl>(*OldParm));
- QualType NewParmType
- = Context.getTypeDeclType(cast<TemplateTypeParmDecl>(*NewParm));
- assert(Context.getCanonicalType(OldParmType) ==
- Context.getCanonicalType(NewParmType) &&
- "type parameter mismatch?");
-#endif
} else if (NonTypeTemplateParmDecl *OldNTTP
= dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) {
// The types of non-type template parameters must agree.
NonTypeTemplateParmDecl *NewNTTP
= cast<NonTypeTemplateParmDecl>(*NewParm);
+
+ // If we are matching a template template argument to a template
+ // template parameter and one of the non-type template parameter types
+ // is dependent, then we must wait until template instantiation time
+ // to actually compare the arguments.
+ if (Kind == TPL_TemplateTemplateArgumentMatch &&
+ (OldNTTP->getType()->isDependentType() ||
+ NewNTTP->getType()->isDependentType()))
+ continue;
+
if (Context.getCanonicalType(OldNTTP->getType()) !=
Context.getCanonicalType(NewNTTP->getType())) {
if (Complain) {
@@ -2389,7 +2620,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
}
Diag(NewNTTP->getLocation(), NextDiag)
<< NewNTTP->getType()
- << IsTemplateTemplateParm;
+ << (Kind != TPL_TemplateMatch);
Diag(OldNTTP->getLocation(),
diag::note_template_nontype_parm_prev_declaration)
<< OldNTTP->getType();
@@ -2399,7 +2630,6 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
} else {
// The template parameter lists of template template
// parameters must agree.
- // FIXME: Could we perform a faster "type" comparison here?
assert(isa<TemplateTemplateParmDecl>(*OldParm) &&
"Only template template parameters handled here");
TemplateTemplateParmDecl *OldTTP
@@ -2409,7 +2639,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
OldTTP->getTemplateParameters(),
Complain,
- /*IsTemplateTemplateParm=*/true,
+ (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind),
TemplateArgLoc))
return false;
}
@@ -2635,16 +2865,9 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs(
} else if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(
TemplateParams->getParam(I))) {
- // FIXME: We should settle on either Declaration storage or
- // Expression storage for template template parameters.
+ TemplateName Name = ArgList[I].getAsTemplate();
TemplateTemplateParmDecl *ArgDecl
- = dyn_cast_or_null<TemplateTemplateParmDecl>(
- ArgList[I].getAsDecl());
- if (!ArgDecl)
- if (DeclRefExpr *DRE
- = dyn_cast_or_null<DeclRefExpr>(ArgList[I].getAsExpr()))
- ArgDecl = dyn_cast<TemplateTemplateParmDecl>(DRE->getDecl());
-
+ = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
if (!ArgDecl ||
ArgDecl->getIndex() != TTP->getIndex() ||
ArgDecl->getDepth() != TTP->getDepth())
@@ -2724,7 +2947,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
@@ -2733,7 +2955,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Find the class template we're specializing
TemplateName Name = TemplateD.getAsVal<TemplateName>();
ClassTemplateDecl *ClassTemplate
- = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
+ = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
+
+ if (!ClassTemplate) {
+ Diag(TemplateNameLoc, diag::err_not_class_template_specialization)
+ << (Name.getAsTemplateDecl() &&
+ isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()));
+ return true;
+ }
bool isExplicitSpecialization = false;
bool isPartialSpecialization = false;
@@ -2772,12 +3001,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
}
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
- if (Expr *DefArg = TTP->getDefaultArgument()) {
- Diag(TTP->getDefaultArgumentLoc(),
+ if (TTP->hasDefaultArgument()) {
+ Diag(TTP->getDefaultArgument().getLocation(),
diag::err_default_arg_in_partial_spec)
- << DefArg->getSourceRange();
- TTP->setDefaultArgument(0);
- DefArg->Destroy(Context);
+ << TTP->getDefaultArgument().getSourceRange();
+ TTP->setDefaultArgument(TemplateArgumentLoc());
}
}
}
@@ -2819,7 +3047,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
// Check that the template argument list is well-formed for this
// template.
@@ -3625,7 +3853,6 @@ Sema::ActOnExplicitInstantiation(Scope *S,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr) {
// Find the class template we're specializing
@@ -3664,7 +3891,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
// Check that the template argument list is well-formed for this
// template.
@@ -3966,19 +4193,16 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
: TSK_ExplicitInstantiationDeclaration;
- LookupResult Previous;
- LookupParsedName(Previous, S, &D.getCXXScopeSpec(),
- Name, LookupOrdinaryName);
+ LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName);
+ LookupParsedName(Previous, S, &D.getCXXScopeSpec());
if (!R->isFunctionType()) {
// C++ [temp.explicit]p1:
// A [...] static data member of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
- if (Previous.isAmbiguous()) {
- return DiagnoseAmbiguousLookup(Previous, Name, D.getIdentifierLoc(),
- D.getSourceRange());
- }
+ if (Previous.isAmbiguous())
+ return true;
VarDecl *Prev = dyn_cast_or_null<VarDecl>(
Previous.getAsSingleDecl(Context));
@@ -4047,10 +4271,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateArgs);
HasExplicitTemplateArgs = true;
TemplateArgsPtr.release();
@@ -4259,11 +4481,11 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II,
assert(Ctx && "No declaration context?");
DeclarationName Name(&II);
- LookupResult Result;
- LookupQualifiedName(Result, Ctx, Name, LookupOrdinaryName, false);
+ LookupResult Result(*this, Name, Range.getEnd(), LookupOrdinaryName);
+ LookupQualifiedName(Result, Ctx);
unsigned DiagID = 0;
Decl *Referenced = 0;
- switch (Result.getKind()) {
+ switch (Result.getResultKind()) {
case LookupResult::NotFound:
DiagID = diag::err_typename_nested_not_found;
break;
@@ -4280,13 +4502,16 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II,
Referenced = Result.getFoundDecl();
break;
+ case LookupResult::FoundUnresolvedValue:
+ llvm::llvm_unreachable("unresolved using decl in non-dependent context");
+ return QualType();
+
case LookupResult::FoundOverloaded:
DiagID = diag::err_typename_nested_not_type;
Referenced = *Result.begin();
break;
case LookupResult::Ambiguous:
- DiagnoseAmbiguousLookup(Result, Name, Range.getEnd(), Range);
return QualType();
}
@@ -4436,12 +4661,24 @@ QualType Sema::RebuildTypeInCurrentInstantiation(QualType T, SourceLocation Loc,
std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
const TemplateArgumentList &Args) {
+ // FIXME: For variadic templates, we'll need to get the structured list.
+ return getTemplateArgumentBindingsText(Params, Args.getFlatArgumentList(),
+ Args.flat_size());
+}
+
+std::string
+Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
std::string Result;
- if (!Params || Params->size() == 0)
+ if (!Params || Params->size() == 0 || NumArgs == 0)
return Result;
for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+ if (I >= NumArgs)
+ break;
+
if (I == 0)
Result += "[with ";
else
@@ -4484,6 +4721,14 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
break;
}
+ case TemplateArgument::Template: {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ Args[I].getAsTemplate().print(OS, Context.PrintingPolicy);
+ Result += OS.str();
+ break;
+ }
+
case TemplateArgument::Integral: {
Result += Args[I].getAsIntegral()->toString(10);
break;
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 7b5ad7fc640e..10594c728fbe 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -126,7 +126,6 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
/// from the given type- or value-dependent expression.
///
/// \returns true if deduction succeeded, false otherwise.
-
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(ASTContext &Context,
NonTypeTemplateParmDecl *NTTP,
@@ -166,34 +165,87 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
return Sema::TDK_Success;
}
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given declaration.
+///
+/// \returns true if deduction succeeded, false otherwise.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(ASTContext &Context,
+ NonTypeTemplateParmDecl *NTTP,
+ Decl *D,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+ assert(NTTP->getDepth() == 0 &&
+ "Cannot deduce non-type template argument with depth > 0");
+
+ if (Deduced[NTTP->getIndex()].isNull()) {
+ Deduced[NTTP->getIndex()] = TemplateArgument(D->getCanonicalDecl());
+ return Sema::TDK_Success;
+ }
+
+ if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
+ // Okay, we deduced a declaration in one case and a dependent expression
+ // in another case.
+ return Sema::TDK_Success;
+ }
+
+ if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Declaration) {
+ // Compare the declarations for equality
+ if (Deduced[NTTP->getIndex()].getAsDecl()->getCanonicalDecl() ==
+ D->getCanonicalDecl())
+ return Sema::TDK_Success;
+
+ // FIXME: Fill in argument mismatch information
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ return Sema::TDK_Success;
+}
+
static Sema::TemplateDeductionResult
DeduceTemplateArguments(ASTContext &Context,
+ TemplateParameterList *TemplateParams,
TemplateName Param,
TemplateName Arg,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
- // FIXME: Implement template argument deduction for template
- // template parameters.
-
- // FIXME: this routine does not have enough information to produce
- // good diagnostics.
-
TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
- TemplateDecl *ArgDecl = Arg.getAsTemplateDecl();
-
- if (!ParamDecl || !ArgDecl) {
- // FIXME: fill in Info.Param/Info.FirstArg
- return Sema::TDK_Inconsistent;
+ if (!ParamDecl) {
+ // The parameter type is dependent and is not a template template parameter,
+ // so there is nothing that we can deduce.
+ return Sema::TDK_Success;
}
-
- ParamDecl = cast<TemplateDecl>(ParamDecl->getCanonicalDecl());
- ArgDecl = cast<TemplateDecl>(ArgDecl->getCanonicalDecl());
- if (ParamDecl != ArgDecl) {
- // FIXME: fill in Info.Param/Info.FirstArg
+
+ if (TemplateTemplateParmDecl *TempParam
+ = dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
+ // Bind the template template parameter to the given template name.
+ TemplateArgument &ExistingArg = Deduced[TempParam->getIndex()];
+ if (ExistingArg.isNull()) {
+ // This is the first deduction for this template template parameter.
+ ExistingArg = TemplateArgument(Context.getCanonicalTemplateName(Arg));
+ return Sema::TDK_Success;
+ }
+
+ // Verify that the previous binding matches this deduction.
+ assert(ExistingArg.getKind() == TemplateArgument::Template);
+ if (Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg))
+ return Sema::TDK_Success;
+
+ // Inconsistent deduction.
+ Info.Param = TempParam;
+ Info.FirstArg = ExistingArg;
+ Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_Inconsistent;
}
-
- return Sema::TDK_Success;
+
+ // Verify that the two template names are equivalent.
+ if (Context.hasSameTemplateName(Param, Arg))
+ return Sema::TDK_Success;
+
+ // Mismatch of non-dependent template parameter to argument.
+ Info.FirstArg = TemplateArgument(Param);
+ Info.SecondArg = TemplateArgument(Arg);
+ return Sema::TDK_NonDeducedMismatch;
}
/// \brief Deduce the template arguments by comparing the template parameter
@@ -224,32 +276,20 @@ DeduceTemplateArguments(ASTContext &Context,
assert(Arg.isCanonical() && "Argument type must be canonical");
// Check whether the template argument is a dependent template-id.
- // FIXME: This is untested code; it can be tested when we implement
- // partial ordering of class template partial specializations.
if (const TemplateSpecializationType *SpecArg
= dyn_cast<TemplateSpecializationType>(Arg)) {
// Perform template argument deduction for the template name.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context,
+ = DeduceTemplateArguments(Context, TemplateParams,
Param->getTemplateName(),
SpecArg->getTemplateName(),
Info, Deduced))
return Result;
- unsigned NumArgs = Param->getNumArgs();
-
- // FIXME: When one of the template-names refers to a
- // declaration with default template arguments, do we need to
- // fill in those default template arguments here? Most likely,
- // the answer is "yes", but I don't see any references. This
- // issue may be resolved elsewhere, because we may want to
- // instantiate default template arguments when we actually write
- // the template-id.
- if (SpecArg->getNumArgs() != NumArgs)
- return Sema::TDK_NonDeducedMismatch;
// Perform template argument deduction on each template
// argument.
+ unsigned NumArgs = std::min(SpecArg->getNumArgs(), Param->getNumArgs());
for (unsigned I = 0; I != NumArgs; ++I)
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(Context, TemplateParams,
@@ -276,13 +316,12 @@ DeduceTemplateArguments(ASTContext &Context,
// Perform template argument deduction for the template name.
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(Context,
+ TemplateParams,
Param->getTemplateName(),
TemplateName(SpecArg->getSpecializedTemplate()),
Info, Deduced))
return Result;
- // FIXME: Can the # of arguments in the parameter and the argument
- // differ due to default arguments?
unsigned NumArgs = Param->getNumArgs();
const TemplateArgumentList &ArgArgs = SpecArg->getTemplateArgs();
if (NumArgs != ArgArgs.size())
@@ -315,8 +354,8 @@ static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
Qualifiers &Quals) {
assert(T.isCanonical() && "Only operates on canonical types");
if (!isa<ArrayType>(T)) {
- Quals = T.getQualifiers();
- return T.getUnqualifiedType();
+ Quals = T.getLocalQualifiers();
+ return T.getLocalUnqualifiedType();
}
assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
@@ -639,9 +678,9 @@ DeduceTemplateArguments(ASTContext &Context,
// template-name<T> (where template-name refers to a class template)
// template-name<i>
- // TT<T> (TODO)
- // TT<i> (TODO)
- // TT<> (TODO)
+ // TT<T>
+ // TT<i>
+ // TT<>
case Type::TemplateSpecialization: {
const TemplateSpecializationType *SpecParam
= cast<TemplateSpecializationType>(Param);
@@ -785,13 +824,28 @@ DeduceTemplateArguments(ASTContext &Context,
break;
case TemplateArgument::Type:
- assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
- return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
- Arg.getAsType(), Info, Deduced, 0);
-
+ if (Arg.getKind() == TemplateArgument::Type)
+ return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
+ Arg.getAsType(), Info, Deduced, 0);
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::Template:
+ if (Arg.getKind() == TemplateArgument::Template)
+ return DeduceTemplateArguments(Context, TemplateParams,
+ Param.getAsTemplate(),
+ Arg.getAsTemplate(), Info, Deduced);
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
case TemplateArgument::Declaration:
- // FIXME: Implement this check
- assert(false && "Unimplemented template argument deduction case");
+ if (Arg.getKind() == TemplateArgument::Declaration &&
+ Param.getAsDecl()->getCanonicalDecl() ==
+ Arg.getAsDecl()->getCanonicalDecl())
+ return Sema::TDK_Success;
+
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
@@ -829,7 +883,10 @@ DeduceTemplateArguments(ASTContext &Context,
if (Arg.getKind() == TemplateArgument::Expression)
return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(),
Info, Deduced);
-
+ if (Arg.getKind() == TemplateArgument::Declaration)
+ return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsDecl(),
+ Info, Deduced);
+
assert(false && "Type/value mismatch");
Info.FirstArg = Param;
Info.SecondArg = Arg;
@@ -885,13 +942,21 @@ static bool isSameTemplateArg(ASTContext &Context,
return X.getAsDecl()->getCanonicalDecl() ==
Y.getAsDecl()->getCanonicalDecl();
+ case TemplateArgument::Template:
+ return Context.getCanonicalTemplateName(X.getAsTemplate())
+ .getAsVoidPointer() ==
+ Context.getCanonicalTemplateName(Y.getAsTemplate())
+ .getAsVoidPointer();
+
case TemplateArgument::Integral:
return *X.getAsIntegral() == *Y.getAsIntegral();
- case TemplateArgument::Expression:
- // FIXME: We assume that all expressions are distinct, but we should
- // really check their canonical forms.
- return false;
+ case TemplateArgument::Expression: {
+ llvm::FoldingSetNodeID XID, YID;
+ X.getAsExpr()->Profile(XID, Context, true);
+ Y.getAsExpr()->Profile(YID, Context, true);
+ return XID == YID;
+ }
case TemplateArgument::Pack:
if (X.pack_size() != Y.pack_size())
@@ -1030,15 +1095,6 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
Info.FirstArg = Partial->getTemplateArgs()[I];
return TDK_SubstitutionFailure;
}
- } else if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Param)) {
- // FIXME: template template arguments should really resolve to decls
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr);
- if (!DRE || CheckTemplateArgument(TTP, DRE)) {
- Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = Partial->getTemplateArgs()[I];
- return TDK_SubstitutionFailure;
- }
}
}
@@ -1384,16 +1440,16 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// - If A is a cv-qualified type, the top level cv-qualifiers of A’s
// type are ignored for type deduction.
QualType CanonArgType = Context.getCanonicalType(ArgType);
- if (CanonArgType.getCVRQualifiers())
- ArgType = CanonArgType.getUnqualifiedType();
+ if (CanonArgType.getLocalCVRQualifiers())
+ ArgType = CanonArgType.getLocalUnqualifiedType();
}
}
// C++0x [temp.deduct.call]p3:
// If P is a cv-qualified type, the top level cv-qualifiers of P’s type
// are ignored for type deduction.
- if (CanonParamType.getCVRQualifiers())
- ParamType = CanonParamType.getUnqualifiedType();
+ if (CanonParamType.getLocalCVRQualifiers())
+ ParamType = CanonParamType.getLocalUnqualifiedType();
if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
// [...] If P is a reference type, the type referred to by P is used
// for type deduction.
@@ -2074,6 +2130,7 @@ Sema::getMoreSpecializedPartialSpecialization(
0);
// Determine whether PS2 is at least as specialized as PS1
+ Deduced.clear();
Deduced.resize(PS1->getTemplateParameters()->size());
bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(Context,
PS1->getTemplateParameters(),
@@ -2153,6 +2210,9 @@ MarkUsedTemplateParameters(Sema &SemaRef,
return;
}
+ if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
+ MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced,
+ Depth, Used);
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced,
Depth, Used);
@@ -2309,6 +2369,7 @@ MarkUsedTemplateParameters(Sema &SemaRef,
switch (TemplateArg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
break;
case TemplateArgument::Type:
@@ -2316,12 +2377,9 @@ MarkUsedTemplateParameters(Sema &SemaRef,
Depth, Used);
break;
- case TemplateArgument::Declaration:
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) {
- if (TTP->getDepth() == Depth)
- Used[TTP->getIndex()] = true;
- }
+ case TemplateArgument::Template:
+ MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(),
+ OnlyDeduced, Depth, Used);
break;
case TemplateArgument::Expression:
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index dfe37d8caf17..58fe59e321cf 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -28,11 +28,20 @@ using namespace clang;
/// \brief Retrieve the template argument list(s) that should be used to
/// instantiate the definition of the given declaration.
+///
+/// \param D the declaration for which we are computing template instantiation
+/// arguments.
+///
+/// \param Innermost if non-NULL, the innermost template argument list.
MultiLevelTemplateArgumentList
-Sema::getTemplateInstantiationArgs(NamedDecl *D) {
+Sema::getTemplateInstantiationArgs(NamedDecl *D,
+ const TemplateArgumentList *Innermost) {
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
+ if (Innermost)
+ Result.addOuterTemplateArguments(Innermost);
+
DeclContext *Ctx = dyn_cast<DeclContext>(D);
if (!Ctx)
Ctx = D->getDeclContext();
@@ -87,6 +96,23 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
return Result;
}
+bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
+ switch (Kind) {
+ case TemplateInstantiation:
+ case DefaultTemplateArgumentInstantiation:
+ case DefaultFunctionArgumentInstantiation:
+ return true;
+
+ case ExplicitTemplateArgumentSubstitution:
+ case DeducedTemplateArgumentSubstitution:
+ case PriorTemplateArgumentSubstitution:
+ case DefaultTemplateArgumentChecking:
+ return false;
+ }
+
+ return true;
+}
+
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Decl *Entity,
@@ -104,7 +130,6 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Inst.NumTemplateArgs = 0;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
}
}
@@ -128,7 +153,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
}
}
@@ -152,7 +176,9 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
+
+ if (!Inst.isInstantiationRecord())
+ ++SemaRef.NonInstantiationEntries;
}
}
@@ -164,48 +190,119 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind
- = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
- Inst.TemplateArgs = TemplateArgs;
- Inst.NumTemplateArgs = NumTemplateArgs;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
- }
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
}
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
- SourceLocation PointOfInstantation,
+ SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
- Invalid = CheckInstantiationDepth(PointOfInstantation, InstantiationRange);
+ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
if (!Invalid) {
ActiveTemplateInstantiation Inst;
Inst.Kind
= ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
- Inst.PointOfInstantiation = PointOfInstantation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = reinterpret_cast<uintptr_t>(Param);
Inst.TemplateArgs = TemplateArgs;
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
}
}
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange) : SemaRef(SemaRef) {
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange) : SemaRef(SemaRef) {
+ Invalid = false;
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NamedDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange) : SemaRef(SemaRef) {
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
+ if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+ assert(SemaRef.NonInstantiationEntries > 0);
+ --SemaRef.NonInstantiationEntries;
+ }
+
SemaRef.ActiveTemplateInstantiations.pop_back();
Invalid = true;
}
@@ -214,8 +311,11 @@ void Sema::InstantiatingTemplate::Clear() {
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
SourceLocation PointOfInstantiation,
SourceRange InstantiationRange) {
- if (SemaRef.ActiveTemplateInstantiations.size()
- <= SemaRef.getLangOptions().InstantiationDepth)
+ assert(SemaRef.NonInstantiationEntries <=
+ SemaRef.ActiveTemplateInstantiations.size());
+ if ((SemaRef.ActiveTemplateInstantiations.size() -
+ SemaRef.NonInstantiationEntries)
+ <= SemaRef.getLangOptions().InstantiationDepth)
return false;
SemaRef.Diag(PointOfInstantiation,
@@ -322,6 +422,34 @@ void Sema::PrintInstantiationStack() {
break;
}
+ case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: {
+ NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity);
+ std::string Name;
+ if (!Parm->getName().empty())
+ Name = std::string(" '") + Parm->getName().str() + "'";
+
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_prior_template_arg_substitution)
+ << isa<TemplateTemplateParmDecl>(Parm)
+ << Name
+ << getTemplateArgumentBindingsText(
+ Active->Template->getTemplateParameters(),
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ break;
+ }
+
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_template_default_arg_checking)
+ << getTemplateArgumentBindingsText(
+ Active->Template->getTemplateParameters(),
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ break;
+ }
}
}
}
@@ -332,18 +460,20 @@ bool Sema::isSFINAEContext() const {
Active = ActiveTemplateInstantiations.rbegin(),
ActiveEnd = ActiveTemplateInstantiations.rend();
Active != ActiveEnd;
- ++Active) {
-
+ ++Active)
+ {
switch(Active->Kind) {
case ActiveTemplateInstantiation::TemplateInstantiation:
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
-
// This is a template instantiation, so there is no SFINAE.
return false;
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
- // A default template argument instantiation may or may not be a
- // SFINAE context; look further up the stack.
+ case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking:
+ // A default template argument instantiation and substitution into
+ // template parameters with arguments for prior parameters may or may
+ // not be a SFINAE context; look further up the stack.
break;
case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
@@ -427,6 +557,9 @@ namespace {
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E,
bool isAddressOfOperand);
+ Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E,
+ bool isAddressOfOperand);
+
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
@@ -440,10 +573,11 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) {
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
- assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() &&
+ TemplateName Template
+ = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
+ assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
- return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(),
- TTP->getPosition()).getAsDecl());
+ return Template.getAsTemplateDecl();
}
// If the corresponding template argument is NULL or non-existent, it's
@@ -454,9 +588,8 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) {
TTP->getPosition()))
return D;
- // FIXME: Implement depth reduction of template template parameters
- assert(false &&
- "Reducing depth of template template parameters is not yet implemented");
+ // Fall through to find the instantiated declaration for this template
+ // template parameter.
}
return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs);
@@ -567,7 +700,6 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
if (NTTP->getDepth() < TemplateArgs.getNumLevels()) {
-
// If the corresponding template argument is NULL or non-existent, it's
// because we are performing instantiation from explicitly-specified
// template arguments in a function template, but there were some
@@ -592,7 +724,38 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
if (!VD)
return SemaRef.ExprError();
- return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
+ if (VD->getDeclContext()->isRecord()) {
+ // If the value is a class member, we might have a pointer-to-member.
+ // Determine whether the non-type template template parameter is of
+ // pointer-to-member type. If so, we need to build an appropriate
+ // expression for a pointer-to-member, since a "normal" DeclRefExpr
+ // would refer to the member itself.
+ if (NTTP->getType()->isMemberPointerType()) {
+ QualType ClassType
+ = SemaRef.Context.getTypeDeclType(
+ cast<RecordDecl>(VD->getDeclContext()));
+ NestedNameSpecifier *Qualifier
+ = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+ ClassType.getTypePtr());
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ OwningExprResult RefExpr
+ = SemaRef.BuildDeclRefExpr(VD,
+ VD->getType().getNonReferenceType(),
+ E->getLocation(),
+ /*FIXME:*/false, /*FIXME:*/false,
+ &SS);
+ if (RefExpr.isInvalid())
+ return SemaRef.ExprError();
+
+ return SemaRef.CreateBuiltinUnaryOp(E->getLocation(),
+ UnaryOperator::AddrOf,
+ move(RefExpr));
+ }
+ }
+
+ return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
+ E->getLocation(),
/*FIXME:*/false, /*FIXME:*/false);
}
@@ -625,10 +788,46 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
if (!InstD)
return SemaRef.ExprError();
- // If we instantiated an UnresolvedUsingDecl and got back an UsingDecl,
- // we need to get the underlying decl.
- // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this?
- InstD = InstD->getUnderlyingDecl();
+ // Flatten using declarations into their shadow declarations.
+ if (isa<UsingDecl>(InstD)) {
+ UsingDecl *UD = cast<UsingDecl>(InstD);
+
+ bool HasNonFunction = false;
+
+ llvm::SmallVector<NamedDecl*, 8> Decls;
+ for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+ E = UD->shadow_end(); I != E; ++I) {
+ NamedDecl *TD = (*I)->getTargetDecl();
+ if (!TD->isFunctionOrFunctionTemplate())
+ HasNonFunction = true;
+
+ Decls.push_back(TD);
+ }
+
+ if (Decls.empty())
+ return SemaRef.ExprError();
+
+ if (Decls.size() == 1)
+ InstD = Decls[0];
+ else if (!HasNonFunction) {
+ OverloadedFunctionDecl *OFD
+ = OverloadedFunctionDecl::Create(SemaRef.Context,
+ UD->getDeclContext(),
+ UD->getDeclName());
+ for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(),
+ E = Decls.end(); I != E; ++I)
+ if (isa<FunctionDecl>(*I))
+ OFD->addOverload(cast<FunctionDecl>(*I));
+ else
+ OFD->addOverload(cast<FunctionTemplateDecl>(*I));
+
+ InstD = OFD;
+ } else {
+ // FIXME
+ assert(false && "using declaration resolved to mixed set");
+ return SemaRef.ExprError();
+ }
+ }
CXXScopeSpec SS;
NestedNameSpecifier *Qualifier = 0;
@@ -648,6 +847,15 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
isAddressOfOperand);
}
+Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
+ CXXDefaultArgExpr *E, bool isAddressOfOperand) {
+ assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
+ getDescribedFunctionTemplate() &&
+ "Default arg expressions are never formed in dependent cases.");
+ return SemaRef.Owned(E->Retain());
+}
+
+
QualType
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL) {
@@ -889,9 +1097,9 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Member != MemberEnd; ++Member) {
Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
if (NewMember) {
- if (NewMember->isInvalidDecl())
+ if (NewMember->isInvalidDecl()) {
Invalid = true;
- else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+ } else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
Fields.push_back(DeclPtrTy::make(Field));
else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember))
Instantiation->addDecl(UD);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 7288ae29a0e3..7e618cd4faea 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===/
#include "Sema.h"
+#include "Lookup.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
@@ -28,6 +29,8 @@ namespace {
DeclContext *Owner;
const MultiLevelTemplateArgumentList &TemplateArgs;
+ void InstantiateAttrs(Decl *Tmpl, Decl *New);
+
public:
typedef Sema::OwningExprResult OwningExprResult;
@@ -62,11 +65,19 @@ namespace {
Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
- Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
+ Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
// Base case. FIXME: Remove once we can instantiate everything.
- Decl *VisitDecl(Decl *) {
- assert(false && "Template instantiation of unknown declaration kind!");
+ Decl *VisitDecl(Decl *D) {
+ unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
+ Diagnostic::Error,
+ "cannot instantiate %0 yet");
+ SemaRef.Diag(D->getLocation(), DiagID)
+ << D->getDeclKindName();
+
return 0;
}
@@ -89,6 +100,18 @@ namespace {
};
}
+// FIXME: Is this too simple?
+void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
+ for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
+ TmplAttr = TmplAttr->getNext()) {
+
+ // FIXME: Is cloning correct for all attributes?
+ Attr *NewAttr = TmplAttr->clone(SemaRef.Context);
+
+ New->addAttr(NewAttr);
+ }
+}
+
Decl *
TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
assert(false && "Translation units cannot be instantiated");
@@ -172,6 +195,15 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
= SemaRef.SubstExpr(D->getInit(), TemplateArgs);
if (Init.isInvalid())
Var->setInvalidDecl();
+ else if (!D->getType()->isDependentType() &&
+ !D->getInit()->isTypeDependent() &&
+ !D->getInit()->isValueDependent()) {
+ // If neither the declaration's type nor its initializer are dependent,
+ // we don't want to redo all the checking, especially since the
+ // initializer might have been wrapped by a CXXConstructExpr since we did
+ // it the first time.
+ Var->setInit(SemaRef.Context, Init.takeAs<Expr>());
+ }
else if (ParenListExpr *PLE = dyn_cast<ParenListExpr>((Expr *)Init.get())) {
// FIXME: We're faking all of the comma locations, which is suboptimal.
// Do we even need these comma locations?
@@ -258,6 +290,8 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
return 0;
}
+ InstantiateAttrs(D, Field);
+
if (Invalid)
Field->setInvalidDecl();
@@ -632,6 +666,12 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
TemplateParams, Function);
Function->setDescribedFunctionTemplate(FunctionTemplate);
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+ } else if (FunctionTemplate) {
+ // Record this function template specialization.
+ Function->setFunctionTemplateSpecialization(SemaRef.Context,
+ FunctionTemplate,
+ &TemplateArgs.getInnermost(),
+ InsertPos);
}
if (InitFunctionInstantiation(Function, D))
@@ -645,9 +685,10 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
// Look only into the namespace where the friend would be declared to
// find a previous declaration. This is the innermost enclosing namespace,
// as described in ActOnFriendFunctionDecl.
- Sema::LookupResult R;
- SemaRef.LookupQualifiedName(R, DC, Function->getDeclName(),
- Sema::LookupOrdinaryName, true);
+ LookupResult R(SemaRef, Function->getDeclName(), SourceLocation(),
+ Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
+ SemaRef.LookupQualifiedName(R, DC);
PrevDecl = R.getAsSingleDecl(SemaRef.Context);
@@ -683,14 +724,6 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
}
- if (FunctionTemplate && !TemplateParams) {
- // Record this function template specialization.
- Function->setFunctionTemplateSpecialization(SemaRef.Context,
- FunctionTemplate,
- &TemplateArgs.getInnermost(),
- InsertPos);
- }
-
return Function;
}
@@ -785,9 +818,17 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
if (D->isOutOfLine())
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
Method->setDescribedFunctionTemplate(FunctionTemplate);
- } else if (!FunctionTemplate)
+ } else if (FunctionTemplate) {
+ // Record this function template specialization.
+ Method->setFunctionTemplateSpecialization(SemaRef.Context,
+ FunctionTemplate,
+ &TemplateArgs.getInnermost(),
+ InsertPos);
+ } else {
+ // Record that this is an instantiation of a member function.
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
-
+ }
+
// If we are instantiating a member function defined
// out-of-line, the instantiation will have the same lexical
// context (which will be a namespace scope) as the template.
@@ -805,8 +846,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
NamedDecl *PrevDecl = 0;
if (!FunctionTemplate || TemplateParams) {
- Sema::LookupResult R;
- SemaRef.LookupQualifiedName(R, Owner, Name, Sema::LookupOrdinaryName, true);
+ LookupResult R(SemaRef, Name, SourceLocation(),
+ Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
+ SemaRef.LookupQualifiedName(R, Owner);
PrevDecl = R.getAsSingleDecl(SemaRef.Context);
// In C++, the previous declaration we find might be a tag type
@@ -817,13 +860,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
PrevDecl = 0;
}
- if (FunctionTemplate && !TemplateParams)
- // Record this function template specialization.
- Method->setFunctionTemplateSpecialization(SemaRef.Context,
- FunctionTemplate,
- &TemplateArgs.getInnermost(),
- InsertPos);
-
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration,
@@ -898,18 +934,8 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
D->wasDeclaredWithTypename(),
D->isParameterPack());
- // FIXME: Do we actually want to perform substitution here? I don't think
- // we do.
- if (D->hasDefaultArgument()) {
- DeclaratorInfo *DefaultPattern = D->getDefaultArgumentInfo();
- DeclaratorInfo *DefaultInst
- = SemaRef.SubstType(DefaultPattern, TemplateArgs,
- D->getDefaultArgumentLoc(),
- D->getDeclName());
-
- Inst->setDefaultArgument(DefaultInst,
- D->defaultArgumentWasInherited() /* preserve? */);
- }
+ if (D->hasDefaultArgument())
+ Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);
// Introduce this template parameter's instantiation into the instantiation
// scope.
@@ -959,7 +985,75 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
}
Decl *
-TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
+TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
+ TemplateTemplateParmDecl *D) {
+ // Instantiate the template parameter list of the template template parameter.
+ TemplateParameterList *TempParams = D->getTemplateParameters();
+ TemplateParameterList *InstParams;
+ {
+ // Perform the actual substitution of template parameters within a new,
+ // local instantiation scope.
+ Sema::LocalInstantiationScope Scope(SemaRef);
+ InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return NULL;
+ }
+
+ // Build the template template parameter.
+ TemplateTemplateParmDecl *Param
+ = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getDepth() - 1, D->getPosition(),
+ D->getIdentifier(), InstParams);
+ Param->setDefaultArgument(D->getDefaultArgument());
+
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+
+ return Param;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ // Using directives are never dependent, so they require no explicit
+
+ UsingDirectiveDecl *Inst
+ = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getNamespaceKeyLocation(),
+ D->getQualifierRange(), D->getQualifier(),
+ D->getIdentLocation(),
+ D->getNominatedNamespace(),
+ D->getCommonAncestor());
+ Owner->addDecl(Inst);
+ return Inst;
+}
+
+Decl * TemplateDeclInstantiator
+ ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+ NestedNameSpecifier *NNS =
+ SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
+ D->getTargetNestedNameRange(),
+ TemplateArgs);
+ if (!NNS)
+ return 0;
+
+ CXXScopeSpec SS;
+ SS.setRange(D->getTargetNestedNameRange());
+ SS.setScopeRep(NNS);
+
+ NamedDecl *UD =
+ SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+ D->getUsingLoc(), SS, D->getLocation(),
+ D->getDeclName(), 0,
+ /*instantiation*/ true,
+ /*typename*/ true, D->getTypenameLoc());
+ if (UD)
+ SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
+ D);
+ return UD;
+}
+
+Decl * TemplateDeclInstantiator
+ ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
NestedNameSpecifier *NNS =
SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
D->getTargetNestedNameRange(),
@@ -972,9 +1066,11 @@ TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
SS.setScopeRep(NNS);
NamedDecl *UD =
- SemaRef.BuildUsingDeclaration(D->getLocation(), SS,
- D->getTargetNameLocation(),
- D->getTargetName(), 0, D->isTypeName());
+ SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+ D->getUsingLoc(), SS, D->getLocation(),
+ D->getDeclName(), 0,
+ /*instantiation*/ true,
+ /*typename*/ false, SourceLocation());
if (UD)
SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
D);
@@ -1006,7 +1102,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
PI != PE; ++PI) {
NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI));
Params.push_back(D);
- Invalid = Invalid || !D;
+ Invalid = Invalid || !D || D->isInvalidDecl();
}
// Clean up if we had an error.
@@ -1240,6 +1336,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
(void) FunTmpl;
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+ --SemaRef.NonInstantiationEntries;
}
}
@@ -1656,7 +1753,13 @@ static bool isInstantiationOf(EnumDecl *Pattern,
return false;
}
-static bool isInstantiationOf(UnresolvedUsingDecl *Pattern,
+static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
+ UsingDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
@@ -1679,7 +1782,15 @@ static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
if (D->getKind() != Other->getKind()) {
- if (UnresolvedUsingDecl *UUD = dyn_cast<UnresolvedUsingDecl>(D)) {
+ if (UnresolvedUsingTypenameDecl *UUD
+ = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+ if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+ return isInstantiationOf(UUD, UD, Ctx);
+ }
+ }
+
+ if (UnresolvedUsingValueDecl *UUD
+ = dyn_cast<UnresolvedUsingValueDecl>(D)) {
if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
return isInstantiationOf(UUD, UD, Ctx);
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index f003127f149f..00dc809f51a8 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -229,7 +229,8 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){
case DeclSpec::TST_enum:
case DeclSpec::TST_union:
case DeclSpec::TST_struct: {
- TypeDecl *D = cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep()));
+ TypeDecl *D
+ = dyn_cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep()));
if (!D) {
// This can happen in C++ with ambiguous lookups.
Result = Context.IntTy;
@@ -1703,7 +1704,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
// class template specialization, or an array with known size of such,
// try to instantiate it.
QualType MaybeTemplate = T;
- if (const ConstantArrayType *Array = T->getAs<ConstantArrayType>())
+ if (const ConstantArrayType *Array = Context.getAsConstantArrayType(T))
MaybeTemplate = Array->getElementType();
if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 767725a1f318..2bee32aa0fc8 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1063,8 +1063,18 @@ public:
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildInitList(SourceLocation LBraceLoc,
MultiExprArg Inits,
- SourceLocation RBraceLoc) {
- return SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc);
+ SourceLocation RBraceLoc,
+ QualType ResultTy) {
+ OwningExprResult Result
+ = SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc);
+ if (Result.isInvalid() || ResultTy->isDependentType())
+ return move(Result);
+
+ // Patch in the result type we were given, which may have been computed
+ // when the initial InitListExpr was built.
+ InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get());
+ ILE->setType(ResultTy);
+ return move(Result);
}
/// \brief Build a new designated initializer expression.
@@ -1699,7 +1709,7 @@ Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
if (E.isInvalid())
return getSema().StmtError();
- return getSema().Owned(E.takeAs<Stmt>());
+ return getSema().ActOnExprStmt(getSema().FullExpr(E));
}
}
@@ -1947,6 +1957,10 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
break;
+ case TemplateArgument::Template:
+ Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
+ break;
+
case TemplateArgument::Expression:
Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
break;
@@ -1987,7 +2001,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
DeclarationName Name;
if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
Name = ND->getDeclName();
- TemporaryBase Rebase(*this, SourceLocation(), Name);
+ TemporaryBase Rebase(*this, Input.getLocation(), Name);
Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
if (!D) return true;
@@ -2008,6 +2022,19 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
return false;
}
+ case TemplateArgument::Template: {
+ TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName());
+ TemplateName Template
+ = getDerived().TransformTemplateName(Arg.getAsTemplate());
+ if (Template.isNull())
+ return true;
+
+ Output = TemplateArgumentLoc(TemplateArgument(Template),
+ Input.getTemplateQualifierRange(),
+ Input.getTemplateNameLoc());
+ return false;
+ }
+
case TemplateArgument::Expression: {
// Template argument expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(getSema(),
@@ -2119,7 +2146,7 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
QualifiedTypeLoc T) {
- Qualifiers Quals = T.getType().getQualifiers();
+ Qualifiers Quals = T.getType().getLocalQualifiers();
QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
if (Result.isNull())
@@ -3893,7 +3920,7 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E,
return SemaRef.Owned(E->Retain());
return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits),
- E->getRBraceLoc());
+ E->getRBraceLoc(), E->getType());
}
template<typename Derived>
@@ -5279,7 +5306,7 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
QualType T) {
if (T->isDependentType() || T->isRecordType() ||
(SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
- assert(!T.hasQualifiers() && "Can't get cv-qualifiers here");
+ assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here");
return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
T.getTypePtr());
}
@@ -5363,6 +5390,9 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
return getSema().CreateBuiltinArraySubscriptExpr(move(First),
DRE->getLocStart(),
move(Second), OpLoc);
+ } else if (Op == OO_Arrow) {
+ // -> is never a builtin operation.
+ return SemaRef.BuildOverloadedArrowExpr(0, move(First), OpLoc);
} else if (SecondExpr == 0 || isPostIncDec) {
if (!FirstExpr->getType()->isOverloadableType()) {
// The argument is not of overloadable type, so try to create a
diff --git a/test/Analysis/CFDateGC.m b/test/Analysis/CFDateGC.m
index 557e7e8f915c..b23998cfc68f 100644
--- a/test/Analysis/CFDateGC.m
+++ b/test/Analysis/CFDateGC.m
@@ -1,8 +1,8 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=basic %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=range %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify -fobjc-gc -disable-free %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -fobjc-gc %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=basic %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=range %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify -fobjc-gc -disable-free %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -fobjc-gc %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s
//===----------------------------------------------------------------------===//
// The following code is reduced using delta-debugging from
diff --git a/test/Analysis/CFNumber.c b/test/Analysis/CFNumber.c
index f62d2ab569d4..f3d371cbde46 100644
--- a/test/Analysis/CFNumber.c
+++ b/test/Analysis/CFNumber.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
typedef signed long CFIndex;
typedef const struct __CFAllocator * CFAllocatorRef;
diff --git a/test/Analysis/CFRetainRelease_NSAssertionHandler.m b/test/Analysis/CFRetainRelease_NSAssertionHandler.m
index 1ff950725c02..04e9add58b5a 100644
--- a/test/Analysis/CFRetainRelease_NSAssertionHandler.m
+++ b/test/Analysis/CFRetainRelease_NSAssertionHandler.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=basic &&
-// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=basic &&
-// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=region &&
-// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=region
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=basic
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=basic
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=region
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=region
typedef struct objc_selector *SEL;
typedef signed char BOOL;
diff --git a/test/Analysis/CGColorSpace.c b/test/Analysis/CGColorSpace.c
index 2887d47c5118..ae628989cd61 100644
--- a/test/Analysis/CGColorSpace.c
+++ b/test/Analysis/CGColorSpace.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
typedef struct CGColorSpace *CGColorSpaceRef;
extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void);
diff --git a/test/Analysis/CheckNSError.m b/test/Analysis/CheckNSError.m
index 5f92594f30d8..219354b20fdf 100644
--- a/test/Analysis/CheckNSError.m
+++ b/test/Analysis/CheckNSError.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
typedef signed char BOOL;
diff --git a/test/Analysis/MissingDealloc.m b/test/Analysis/MissingDealloc.m
index 41498e56ec1d..3942391ee982 100644
--- a/test/Analysis/MissingDealloc.m
+++ b/test/Analysis/MissingDealloc.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -warn-objc-missing-dealloc '-DIBOutlet=__attribute__((iboutlet))' %s --verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-objc-missing-dealloc '-DIBOutlet=__attribute__((iboutlet))' %s --verify
typedef signed char BOOL;
@protocol NSObject
- (BOOL)isEqual:(id)object;
diff --git a/test/Analysis/NSPanel.m b/test/Analysis/NSPanel.m
index 801620a181bf..20e3efff4c60 100644
--- a/test/Analysis/NSPanel.m
+++ b/test/Analysis/NSPanel.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
// BEGIN delta-debugging reduced header stuff
diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m
index a360075645f8..481a94055ffd 100644
--- a/test/Analysis/NSString.m
+++ b/test/Analysis/NSString.m
@@ -1,13 +1,13 @@
-// RUN: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
// ==-- FIXME: -analyzer-store=basic fails on this file (false negatives). --==
-// NOTWORK: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// NOTWORK: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// NOTWORK: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// NOTWORK: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// NOTWORK: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
+// NOTWORK: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
+// NOTWORK: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
+// NOTWORK: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
//===----------------------------------------------------------------------===//
// The following code is reduced using delta-debugging from
@@ -371,5 +371,4 @@ void test_synchronized(id x) {
NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain]; // expected-warning {{leak}}
}
}
-
-
+@end
diff --git a/test/Analysis/NSWindow.m b/test/Analysis/NSWindow.m
index 9609c5260f53..5eb6cf1e4770 100644
--- a/test/Analysis/NSWindow.m
+++ b/test/Analysis/NSWindow.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -warn-dead-stores -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -warn-dead-stores -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -warn-dead-stores -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -warn-dead-stores -analyzer-store=region -analyzer-constraints=range -verify %s
// These declarations were reduced using Delta-Debugging from Foundation.h
// on Mac OS X. The test cases are below.
diff --git a/test/Analysis/NoReturn.m b/test/Analysis/NoReturn.m
index 5f5ce281a794..cf708b4f8970 100644
--- a/test/Analysis/NoReturn.m
+++ b/test/Analysis/NoReturn.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
#include <stdarg.h>
diff --git a/test/Analysis/ObjCProperties.m b/test/Analysis/ObjCProperties.m
index 3ad256914a42..6c367f427d46 100644
--- a/test/Analysis/ObjCProperties.m
+++ b/test/Analysis/ObjCProperties.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic %s -verify &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range %s -verify &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic %s -verify &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range %s -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic %s -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range %s -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic %s -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range %s -verify
// The point of this test cases is to exercise properties in the static
// analyzer
diff --git a/test/Analysis/ObjCRetSigs.m b/test/Analysis/ObjCRetSigs.m
index 0d699168a551..60a85fd791ed 100644
--- a/test/Analysis/ObjCRetSigs.m
+++ b/test/Analysis/ObjCRetSigs.m
@@ -1,6 +1,6 @@
-// RUN: clang-cc -analyze -warn-objc-methodsigs -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-objc-methodsigs -verify %s
-#include <stdio.h>
+int printf(const char *, ...);
@interface MyBase
-(long long)length;
diff --git a/test/Analysis/PR2599.m b/test/Analysis/PR2599.m
index 098bfe8e8539..fd5ae95d5842 100644
--- a/test/Analysis/PR2599.m
+++ b/test/Analysis/PR2599.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -analyzer-constraints=basic -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s &&
-// RUN: clang-cc -analyze -analyzer-constraints=range -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s &&
-// RUN: clang-cc -analyze -analyzer-constraints=basic -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s &&
-// RUN: clang-cc -analyze -analyzer-constraints=range -analyzer-store=region -checker-cfref -fobjc-gc -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -analyzer-constraints=basic -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -analyzer-constraints=range -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -analyzer-constraints=basic -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -analyzer-constraints=range -analyzer-store=region -checker-cfref -fobjc-gc -verify %s
typedef const void * CFTypeRef;
typedef const struct __CFString * CFStringRef;
diff --git a/test/Analysis/PR2978.m b/test/Analysis/PR2978.m
index 0cb3dea8ea86..8a94fe848993 100644
--- a/test/Analysis/PR2978.m
+++ b/test/Analysis/PR2978.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -warn-objc-missing-dealloc %s -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-objc-missing-dealloc %s -verify
// Tests for the checker which checks missing/extra ivar 'release' calls
// in dealloc.
diff --git a/test/Analysis/PR3991.m b/test/Analysis/PR3991.m
index bbc1377b0415..53a6b5257a77 100644
--- a/test/Analysis/PR3991.m
+++ b/test/Analysis/PR3991.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
//===----------------------------------------------------------------------===//
// Delta-debugging produced forward declarations.
@@ -42,7 +42,15 @@ typedef struct _NSZone NSZone;
- (unsigned int)currentPathComponentIndex;
- (void)setCurrentPathComponentIndex:(unsigned int)aCurrentPathComponentIndex;
- (NSURL *)folderFeedURL;
-@end @implementation IHGoogleDocsAdapter - (id)initWithUsername:(NSString *)inUsername password:(NSString *)inPassword owner:(NSObject <IHGoogleDocsAdapterDelegate> *)owner {
+@end
+
+@implementation IHGoogleDocsAdapter - (id)initWithUsername:(NSString *)inUsername password:(NSString *)inPassword owner:(NSObject <IHGoogleDocsAdapterDelegate> *)owner { // expected-warning {{incomplete implementation}} \
+// expected-warning {{method definition for 'entries' not found}} \
+// expected-warning {{method definition for 'feedDocList' not found}} \
+// expected-warning {{method definition for 'directoryPathComponents' not found}} \
+// expected-warning {{method definition for 'currentPathComponentIndex' not found}} \
+// expected-warning {{method definition for 'setCurrentPathComponentIndex:' not found}} \
+// expected-warning {{method definition for 'folderFeedURL' not found}}
return 0;
}
@@ -66,3 +74,4 @@ typedef struct _NSZone NSZone;
}
}
}
+@end
diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c
index d6b6076a14b2..c3822cdb443a 100644
--- a/test/Analysis/array-struct.c
+++ b/test/Analysis/array-struct.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
struct s {
int data;
@@ -120,7 +120,7 @@ struct s1 {
// building: a->e, e->d. Only then 'a' could be added to live region roots.
void f13(double timeout) {
struct s1 a;
- a.e.d = (long) timeout;
+ a.e.d = (int) timeout;
if (a.e.d == 10)
a.e.d = 4;
}
@@ -153,7 +153,7 @@ struct s3 p[1];
// an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
// assigns to 'a'.
void f16(struct s3 *p) {
- struct s3 a = *((struct s3*) ((char*) &p[0]));
+ struct s3 a = *((struct s3*) ((char*) &p[0])); // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption.}}
}
void inv(struct s1 *);
diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c
index ae51ffb69aa5..fc9e27bfe755 100644
--- a/test/Analysis/casts.c
+++ b/test/Analysis/casts.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref -analyzer-store=region --verify %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region --verify %s
// Test if the 'storage' region gets properly initialized after it is cast to
// 'struct sockaddr *'.
diff --git a/test/Analysis/casts.m b/test/Analysis/casts.m
index 82c29fac904f..4e201bf7eb4c 100644
--- a/test/Analysis/casts.m
+++ b/test/Analysis/casts.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic --verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region --verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic --verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region --verify %s
// Test function pointer casts. Currently we track function addresses using
// loc::FunctionVal. Because casts can be arbitrary, do we need to model
diff --git a/test/Analysis/cfref_PR2519.c b/test/Analysis/cfref_PR2519.c
index 695123b53345..ee1da1fff972 100644
--- a/test/Analysis/cfref_PR2519.c
+++ b/test/Analysis/cfref_PR2519.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=range -verify %s
typedef unsigned char Boolean;
typedef signed long CFIndex;
diff --git a/test/Analysis/cfref_rdar6080742.c b/test/Analysis/cfref_rdar6080742.c
index 9bbaf9b5ae06..a2b7477db8bc 100644
--- a/test/Analysis/cfref_rdar6080742.c
+++ b/test/Analysis/cfref_rdar6080742.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
// This test case was reported in <rdar:problem/6080742>.
// It tests path-sensitivity with respect to '!(cfstring != 0)' (negation of inequality).
diff --git a/test/Analysis/complex.c b/test/Analysis/complex.c
index 3633b2148413..6b71a93e65a9 100644
--- a/test/Analysis/complex.c
+++ b/test/Analysis/complex.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
#include <stdint.h>
diff --git a/test/Analysis/concrete-address.c b/test/Analysis/concrete-address.c
index 84ebb21805a2..31802d038019 100644
--- a/test/Analysis/concrete-address.c
+++ b/test/Analysis/concrete-address.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic --verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region --verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic --verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region --verify %s
void foo() {
int *p = (int*) 0x10000; // Should not crash here.
diff --git a/test/Analysis/conditional-op-missing-lhs.c b/test/Analysis/conditional-op-missing-lhs.c
index bebf155f4640..ed81d7b67200 100644
--- a/test/Analysis/conditional-op-missing-lhs.c
+++ b/test/Analysis/conditional-op-missing-lhs.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -warn-dead-stores -warn-uninit-values -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-dead-stores -warn-uninit-values -verify %s
void f1()
{
diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c
index c4ff7fa0e860..811ac813c7e2 100644
--- a/test/Analysis/dead-stores.c
+++ b/test/Analysis/dead-stores.c
@@ -1,8 +1,8 @@
-// RUN: clang-cc -analyze -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -warn-dead-stores -verify %s
void f1() {
int k, y;
diff --git a/test/Analysis/dead-stores.cpp b/test/Analysis/dead-stores.cpp
index 9ddb7979ca69..0bf32567f9db 100644
--- a/test/Analysis/dead-stores.cpp
+++ b/test/Analysis/dead-stores.cpp
@@ -1,8 +1,8 @@
-// RUN: clang-cc -analyze -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -warn-dead-stores -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -analyzer-constraints=range -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=basic -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -analyzer-constraints=range -warn-dead-stores -verify %s
int j;
void f1() {
diff --git a/test/Analysis/dead-stores.m b/test/Analysis/dead-stores.m
index 218cb4458580..0a5c0f837301 100644
--- a/test/Analysis/dead-stores.m
+++ b/test/Analysis/dead-stores.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-dead-stores -verify %s
typedef signed char BOOL;
typedef unsigned int NSUInteger;
diff --git a/test/Analysis/delegates.m b/test/Analysis/delegates.m
index 440f31113cff..b854da6ec330 100644
--- a/test/Analysis/delegates.m
+++ b/test/Analysis/delegates.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
//===----------------------------------------------------------------------===//
diff --git a/test/Analysis/elementtype.c b/test/Analysis/elementtype.c
index 2bdaad423a39..b6873ad89980 100644
--- a/test/Analysis/elementtype.c
+++ b/test/Analysis/elementtype.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region %s
typedef struct added_obj_st {
int type;
diff --git a/test/Analysis/exercise-ps.c b/test/Analysis/exercise-ps.c
index 1e31b1888e1f..098ec48f4ea3 100644
--- a/test/Analysis/exercise-ps.c
+++ b/test/Analysis/exercise-ps.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
//
// Just exercise the analyzer on code that has at one point caused issues
// (i.e., no assertions or crashes).
diff --git a/test/Analysis/fields.c b/test/Analysis/fields.c
index 900a6d6869ac..d6bc84575ef4 100644
--- a/test/Analysis/fields.c
+++ b/test/Analysis/fields.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=basic -verify &&
-// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=region -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref %s --analyzer-store=basic -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref %s --analyzer-store=region -verify
unsigned foo();
typedef struct bf { unsigned x:2; } bf;
diff --git a/test/Analysis/func.c b/test/Analysis/func.c
index 2b4e7b0db076..390a2793a497 100644
--- a/test/Analysis/func.c
+++ b/test/Analysis/func.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
void f(void) {
void (*p)(void);
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
new file mode 100644
index 000000000000..6a17cba3497b
--- /dev/null
+++ b/test/Analysis/malloc.c
@@ -0,0 +1,37 @@
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-experimental-checks -analyzer-store=region -verify %s
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void free(void *);
+
+void f1() {
+ int *p = malloc(10);
+ return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void f1_b() {
+ int *p = malloc(10); // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void f2() {
+ int *p = malloc(10);
+ free(p);
+ free(p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+// This case tests that storing malloc'ed memory to a static variable which is
+// then returned is not leaked. In the absence of known contracts for functions
+// or inter-procedural analysis, this is a conservative answer.
+int *f3() {
+ static int *p = 0;
+ p = malloc(10);
+ return p; // no-warning
+}
+
+// This case tests that storing malloc'ed memory to a static global variable
+// which is then returned is not leaked. In the absence of known contracts for
+// functions or inter-procedural analysis, this is a conservative answer.
+static int *p_f4 = 0;
+int *f4() {
+ p_f4 = malloc(10);
+ return p_f4; // no-warning
+}
diff --git a/test/Analysis/misc-ps-64.m b/test/Analysis/misc-ps-64.m
index 163da4b4abeb..506dc8b0e530 100644
--- a/test/Analysis/misc-ps-64.m
+++ b/test/Analysis/misc-ps-64.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=basic --verify -fblocks %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic -analyzer-constraints=basic --verify -fblocks %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
// <rdar://problem/6440393> - A bunch of misc. failures involving evaluating
// these expressions and building CFGs. These tests are here to prevent
diff --git a/test/Analysis/misc-ps-basic-store.m b/test/Analysis/misc-ps-basic-store.m
index c6ae20c86a36..2b9913461718 100644
--- a/test/Analysis/misc-ps-basic-store.m
+++ b/test/Analysis/misc-ps-basic-store.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic --verify -fblocks %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic --verify -fblocks %s
//---------------------------------------------------------------------------
// Test case 'checkaccess_union' differs for region store and basic store.
diff --git a/test/Analysis/misc-ps-eager-assume.m b/test/Analysis/misc-ps-eager-assume.m
index db1a80b8efd9..66eb1256f42a 100644
--- a/test/Analysis/misc-ps-eager-assume.m
+++ b/test/Analysis/misc-ps-eager-assume.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s -analyzer-eagerly-assume
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s -analyzer-eagerly-assume
// Delta-reduced header stuff (needed for test cases).
typedef signed char BOOL;
diff --git a/test/Analysis/misc-ps-ranges.m b/test/Analysis/misc-ps-ranges.m
index a191bec3cfb1..49cc5933ccad 100644
--- a/test/Analysis/misc-ps-ranges.m
+++ b/test/Analysis/misc-ps-ranges.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s &&
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
// <rdar://problem/6776949>
// main's 'argc' argument is always > 0
@@ -20,4 +20,4 @@ int main(int argc, char* argv[]) {
}
return *p; // no-warning
-} \ No newline at end of file
+}
diff --git a/test/Analysis/misc-ps-region-store-i386.m b/test/Analysis/misc-ps-region-store-i386.m
index c2c4d5b9413c..a833a653a425 100644
--- a/test/Analysis/misc-ps-region-store-i386.m
+++ b/test/Analysis/misc-ps-region-store-i386.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s
+// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region --verify -fblocks %s
// Here is a case where a pointer is treated as integer, invalidated as an
// integer, and then used again as a pointer. This test just makes sure
diff --git a/test/Analysis/misc-ps-region-store-x86_64.m b/test/Analysis/misc-ps-region-store-x86_64.m
index 154ffaf3a003..7e614fd24833 100644
--- a/test/Analysis/misc-ps-region-store-x86_64.m
+++ b/test/Analysis/misc-ps-region-store-x86_64.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region --verify -fblocks %s
// Here is a case where a pointer is treated as integer, invalidated as an
// integer, and then used again as a pointer. This test just makes sure
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index 4cde7726b49b..7ebc4a9fe5e5 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s
+// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region --verify -fblocks %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region --verify -fblocks %s
typedef struct objc_selector *SEL;
typedef signed char BOOL;
@@ -286,7 +286,7 @@ struct WrappedStruct { unsigned z; };
int test_handle_array_wrapper() {
struct ArrayWrapper x;
test_handle_array_wrapper(&x);
- struct WrappedStruct *p = (struct WrappedStruct*) x.y;
+ struct WrappedStruct *p = (struct WrappedStruct*) x.y; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption.}}
return p->z; // no-warning
}
@@ -431,3 +431,42 @@ pr5316_REFRESH_ELEMENT;
static void pr5316(pr5316_REFRESH_ELEMENT *dst, const pr5316_REFRESH_ELEMENT *src) {
while ((*dst++ = *src++).chr != L'\0') ;
}
+
+//===----------------------------------------------------------------------===//
+// Exercise creating ElementRegion with symbolic super region.
+//===----------------------------------------------------------------------===//
+void element_region_with_symbolic_superregion(int* p) {
+ int *x;
+ int a;
+ if (p[0] == 1)
+ x = &a;
+ if (p[0] == 1)
+ (void)*x; // no-warning
+}
+
+//===----------------------------------------------------------------------===//
+// Test returning an out-of-bounds pointer (CWE-466)
+//===----------------------------------------------------------------------===//
+
+static int test_cwe466_return_outofbounds_pointer_a[10];
+int *test_cwe466_return_outofbounds_pointer() {
+ int *p = test_cwe466_return_outofbounds_pointer_a+10;
+ return p; // expected-warning{{Returned pointer value points outside the original object}}
+}
+
+//===----------------------------------------------------------------------===//
+// PR 3135 - Test case that shows that a variable may get invalidated when its
+// address is included in a structure that is passed-by-value to an unknown function.
+//===----------------------------------------------------------------------===//
+
+typedef struct { int *a; } pr3135_structure;
+int pr3135_bar(pr3135_structure *x);
+int pr3135() {
+ int x;
+ pr3135_structure y = { &x };
+ // the call to pr3135_bar may initialize x
+ if (pr3135_bar(&y) && x) // no-warning
+ return 1;
+ return 0;
+}
+
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index 80e20c1ebb00..d2eef0d7fdbd 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -1,8 +1,8 @@
// NOTE: Use '-fobjc-gc' to test the analysis being run twice, and multiple reports are not issued.
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -fobjc-gc -analyzer-constraints=basic --verify -fblocks %s &&
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s &&
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s &&
-// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic -fobjc-gc -analyzer-constraints=basic --verify -fblocks %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
typedef struct objc_ivar *Ivar;
typedef struct objc_selector *SEL;
@@ -692,7 +692,6 @@ void *rdar7152418_bar();
// conversions of the symbol as necessary.
//===----------------------------------------------------------------------===//
-
// Previously this would crash once we started eagerly evaluating symbols whose
// values were constrained to a single value.
void test_symbol_fold_1(signed char x) {
@@ -722,5 +721,32 @@ unsigned test_symbol_fold_3(void) {
if (x == 54)
return (x << 8) | 0x5;
return 0;
-}
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for the warning of casting a non-struct type to a struct type
+//===----------------------------------------------------------------------===//
+
+typedef struct {unsigned int v;} NSSwappedFloat;
+NSSwappedFloat test_cast_nonstruct_to_struct(float x) {
+ struct hodor {
+ float number;
+ NSSwappedFloat sf;
+ };
+ return ((struct hodor *)&x)->sf; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
+}
+
+NSSwappedFloat test_cast_nonstruct_to_union(float x) {
+ union bran {
+ float number;
+ NSSwappedFloat sf;
+ };
+ return ((union bran *)&x)->sf; // no-warning
+}
+
+void test_undefined_array_subscript() {
+ int i, a[10];
+ int *p = &a[i]; // expected-warning{{Array subscript is undefined}}
+}
+@end
diff --git a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
index 87faab6bfbac..536c4a1b6731 100644
--- a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
+++ b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=basic %s -verify &&
-// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=region %s -verify
+// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-constraints=basic -analyzer-store=basic %s -verify
+// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-constraints=basic -analyzer-store=region %s -verify
@interface MyClass {}
- (void *)voidPtrM;
diff --git a/test/Analysis/no-exit-cfg.c b/test/Analysis/no-exit-cfg.c
index cad2127b2082..af8db135926f 100644
--- a/test/Analysis/no-exit-cfg.c
+++ b/test/Analysis/no-exit-cfg.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
// This is a test case for the issue reported in PR 2819:
// http://llvm.org/bugs/show_bug.cgi?id=2819
diff --git a/test/Analysis/no-outofbounds.c b/test/Analysis/no-outofbounds.c
index 94052806f0aa..475a2116a7c8 100644
--- a/test/Analysis/no-outofbounds.c
+++ b/test/Analysis/no-outofbounds.c
@@ -1,5 +1,6 @@
-// RUN: clang-cc -checker-cfref -analyze -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -checker-cfref -analyze -analyzer-store=region -verify %s
+// RUN: clang-cc -checker-cfref -analyze -analyzer-experimental-internal-checks -analyzer-store=basic -verify %s
+// RUN: clang-cc -checker-cfref -analyze -analyzer-experimental-internal-checks -analyzer-store=region -verify %s
+// XFAIL: *
//===----------------------------------------------------------------------===//
// This file tests cases where we should not flag out-of-bounds warnings.
diff --git a/test/Analysis/null-deref-ps-region.c b/test/Analysis/null-deref-ps-region.c
index 80a5f9212fac..ab1151382573 100644
--- a/test/Analysis/null-deref-ps-region.c
+++ b/test/Analysis/null-deref-ps-region.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -std=gnu99 -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -analyzer-store=region -verify %s
// The store for 'a[1]' should not be removed mistakenly. SymbolicRegions may
diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c
index f37b4416f2a1..4604db542980 100644
--- a/test/Analysis/null-deref-ps.c
+++ b/test/Analysis/null-deref-ps.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -triple i386-apple-darwin10 -analyze -std=gnu99 -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=basic &&
-// RUN: clang-cc -triple i386-apple-darwin10 -analyze -std=gnu99 -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=basic &&
-// RUN: clang-cc -triple i386-apple-darwin10 -analyze -std=gnu99 -checker-cfref -analyzer-store=region -analyzer-constraints=range -analyzer-purge-dead=false -verify %s &&
-// RUN: clang-cc -triple i386-apple-darwin10 -analyze -std=gnu99 -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=basic
+// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=basic
+// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -analyzer-store=region -analyzer-constraints=range -analyzer-purge-dead=false -verify %s
+// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
typedef unsigned uintptr_t;
diff --git a/test/Analysis/outofbound.c b/test/Analysis/outofbound.c
index e676ea3b3889..d1a07abf527f 100644
--- a/test/Analysis/outofbound.c
+++ b/test/Analysis/outofbound.c
@@ -1,8 +1,7 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
-// XFAIL: *
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
char f1() {
char* s = "abcd";
char c = s[4]; // no-warning
- return s[5] + c; // expected-warning{{Load or store into an out-of-bound memory position.}}
+ return s[5] + c; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
}
diff --git a/test/Analysis/override-werror.c b/test/Analysis/override-werror.c
index f928ee031fe3..e8ce7bdc66dd 100644
--- a/test/Analysis/override-werror.c
+++ b/test/Analysis/override-werror.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -Werror %s -analyzer-store=basic -verify &&
-// RUN: clang-cc -analyze -checker-cfref -Werror %s -analyzer-store=region -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -Werror %s -analyzer-store=basic -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -Werror %s -analyzer-store=region -verify
// This test case illustrates that using '-analyze' overrides the effect of
// -Werror. This allows basic warnings not to interfere with producing
diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m
new file mode 100644
index 000000000000..8bd616ade0e8
--- /dev/null
+++ b/test/Analysis/plist-output.m
@@ -0,0 +1,122 @@
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref --analyzer-store=region -analyzer-constraints=range -fblocks --analyzer-output=plist -o - %s | FileCheck %s
+
+void test_null_init(void) {
+ int *p = 0;
+ *p = 0xDEADBEEF;
+}
+// CHECK: <?xml version="1.0" encoding="UTF-8"?>
+// CHECK: <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+// CHECK: <plist version="1.0">
+// CHECK: <dict>
+// CHECK: <key>files</key>
+// CHECK: <array>
+// CHECK: </array>
+// CHECK: <key>diagnostics</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>path</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>event</string>
+// CHECK: <key>location</key>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <key>ranges</key>
+// CHECK: <array>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </array>
+// CHECK: <key>extended_message</key>
+// CHECK: <string>Variable &apos;p&apos; initialized to a null pointer value</string>
+// CHECK: <key>message</key>
+// CHECK: <string>Variable &apos;p&apos; initialized to a null pointer value</string>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>4</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>event</string>
+// CHECK: <key>location</key>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <key>ranges</key>
+// CHECK: <array>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>4</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </array>
+// CHECK: <key>extended_message</key>
+// CHECK: <string>Dereference of null pointer</string>
+// CHECK: <key>message</key>
+// CHECK: <string>Dereference of null pointer</string>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>description</key><string>Dereference of null pointer</string>
+// CHECK: <key>category</key><string>Logic error</string>
+// CHECK: <key>type</key><string>Null pointer dereference</string>
+// CHECK: <key>location</key>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </plist>
diff --git a/test/Analysis/pr4209.m b/test/Analysis/pr4209.m
index 991d0d68f704..60161b1b08a8 100644
--- a/test/Analysis/pr4209.m
+++ b/test/Analysis/pr4209.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
// This test case was crashing due to how CFRefCount.cpp resolved the
// ObjCInterfaceDecl* and ClassName in EvalObjCMessageExpr.
@@ -49,17 +49,20 @@ CMProfileLocation;
GSEbayCategory *rootCategory;
}
- (NSMutableDictionary*)categoryDictionaryForCategoryID:(int)inID inRootTreeCategories:(NSMutableArray*)inRootTreeCategories;
--(NSString*) categoryID;
+-(NSString*) categoryID;
@end @interface GSEbayCategory : NSObject <NSCoding> {
}
- (int) categoryID;
- (GSEbayCategory *) parent;
- (GSEbayCategory*) subcategoryWithID:(int) inID;
-@end @implementation GBCategoryChooserPanelController + (int) chooseCategoryIDFromCategories:(NSArray*) inCategories searchRequest:(GBSearchRequest*)inRequest parentWindow:(NSWindow*) inParent {
+@end @implementation GBCategoryChooserPanelController + (int) chooseCategoryIDFromCategories:(NSArray*) inCategories searchRequest:(GBSearchRequest*)inRequest parentWindow:(NSWindow*) inParent { // expected-warning {{incomplete implementation}} \
+// expected-warning {{method definition for 'categoryDictionaryForCategoryID:inRootTreeCategories:' not found}} \
+// expected-warning {{method definition for 'categoryID' not found}}
return 0;
}
- (void) addCategory:(EBayCategoryType*)inCategory toRootTreeCategory:(NSMutableArray*)inRootTreeCategories {
- GSEbayCategory *category = [rootCategory subcategoryWithID:[[inCategory categoryID] intValue]];
+ GSEbayCategory *category = [rootCategory subcategoryWithID:[[inCategory categoryID] intValue]];
+
if (rootCategory != category) {
GSEbayCategory *parent = category;
while ((((void*)0) != (parent = [parent parent])) && ([parent categoryID] != 0)) {
@@ -69,3 +72,4 @@ CMProfileLocation;
}
}
}
+@end
diff --git a/test/Analysis/pr_2542_rdar_6793404.m b/test/Analysis/pr_2542_rdar_6793404.m
index 82a028d652d1..ebb69028a709 100644
--- a/test/Analysis/pr_2542_rdar_6793404.m
+++ b/test/Analysis/pr_2542_rdar_6793404.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -pedantic -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -pedantic -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -pedantic -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -pedantic -analyzer-store=region -verify %s
// BEGIN delta-debugging reduced header stuff
diff --git a/test/Analysis/pr_4164.c b/test/Analysis/pr_4164.c
index cc2479c3e49c..176871773959 100644
--- a/test/Analysis/pr_4164.c
+++ b/test/Analysis/pr_4164.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
// PR 4164: http://llvm.org/bugs/show_bug.cgi?id=4164
//
diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c
index 4f2c7d9edb0b..b585c85d67fe 100644
--- a/test/Analysis/ptr-arith.c
+++ b/test/Analysis/ptr-arith.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify -triple i686-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify -triple i686-apple-darwin9 %s
void f1() {
int a[10];
@@ -31,3 +31,32 @@ domain_port (const char *domain_b, const char *domain_e,
port = 10 * port + (*p - '0');
return port;
}
+
+void f3() {
+ int x, y;
+ int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point to the same memory chunk may cause incorrect result.}}
+
+ int a[10];
+ int *p = &a[2];
+ int *q = &a[8];
+ d = q-p; // no-warning
+}
+
+void f4() {
+ int *p;
+ p = (int*) 0x10000; // expected-warning{{Using a fixed address is not portable because that address will probably not be valid in all environments or platforms.}}
+}
+
+void f5() {
+ int x, y;
+ int *p;
+ p = &x + 1; // expected-warning{{Pointer arithmetic done on non-array variables means reliance on memory layout, which is dangerous.}}
+
+ int a[10];
+ p = a + 1; // no-warning
+}
+
+// Allow arithmetic on different symbolic regions.
+void f6(int *p, int *q) {
+ int d = q - p; // no-warning
+}
diff --git a/test/Analysis/rdar-6442306-1.m b/test/Analysis/rdar-6442306-1.m
index bfda115360e4..7b0a1a685bdf 100644
--- a/test/Analysis/rdar-6442306-1.m
+++ b/test/Analysis/rdar-6442306-1.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=basic -verify &&
-// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=region -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref %s --analyzer-store=basic -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref %s --analyzer-store=region -verify
typedef int bar_return_t;
typedef struct {
diff --git a/test/Analysis/rdar-6540084.m b/test/Analysis/rdar-6540084.m
index cfe522074ed3..4d191d2f1e35 100644
--- a/test/Analysis/rdar-6540084.m
+++ b/test/Analysis/rdar-6540084.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -warn-dead-stores -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -warn-dead-stores -verify %s
//
// This test exercises the live variables analysis (LiveVariables.cpp).
// The case originally identified a non-termination bug.
diff --git a/test/Analysis/rdar-6541136-region.c b/test/Analysis/rdar-6541136-region.c
index e2779e8d914f..5190a032df8a 100644
--- a/test/Analysis/rdar-6541136-region.c
+++ b/test/Analysis/rdar-6541136-region.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -verify -analyze -checker-cfref -analyzer-store=region %s
+// RUN: clang-cc -verify -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region %s
struct tea_cheese { unsigned magic; };
typedef struct tea_cheese kernel_tea_cheese_t;
@@ -6,17 +6,22 @@ extern kernel_tea_cheese_t _wonky_gesticulate_cheese;
// This test case exercises the ElementRegion::getRValueType() logic.
-
-void foo( void )
-{
+void test1( void ) {
kernel_tea_cheese_t *wonky = &_wonky_gesticulate_cheese;
struct load_wine *cmd = (void*) &wonky[1];
cmd = cmd;
char *p = (void*) &wonky[1];
- *p = 1; // no-warning
kernel_tea_cheese_t *q = &wonky[1];
// This test case tests both the RegionStore logic (doesn't crash) and
// the out-of-bounds checking. We don't expect the warning for now since
// out-of-bound checking is temporarily disabled.
- kernel_tea_cheese_t r = *q; // eventually-warning{{out-of-bound memory position}}
+ kernel_tea_cheese_t r = *q; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
+}
+
+void test1_b( void ) {
+ kernel_tea_cheese_t *wonky = &_wonky_gesticulate_cheese;
+ struct load_wine *cmd = (void*) &wonky[1];
+ cmd = cmd;
+ char *p = (void*) &wonky[1];
+ *p = 1; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
}
diff --git a/test/Analysis/rdar-6541136.c b/test/Analysis/rdar-6541136.c
index 6e6a479136b9..d5fc2e0ff1bd 100644
--- a/test/Analysis/rdar-6541136.c
+++ b/test/Analysis/rdar-6541136.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -verify -analyze -checker-cfref -analyzer-store=basic %s
+// RUN: clang-cc -verify -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic %s
struct tea_cheese { unsigned magic; };
typedef struct tea_cheese kernel_tea_cheese_t;
diff --git a/test/Analysis/rdar-6562655.m b/test/Analysis/rdar-6562655.m
index 3c1c281a830d..0b837c6fa6e7 100644
--- a/test/Analysis/rdar-6562655.m
+++ b/test/Analysis/rdar-6562655.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-constraints=basic -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-constraints=basic -analyzer-store=region -verify %s
//
// This test case mainly checks that the retain/release checker doesn't crash
// on this file.
diff --git a/test/Analysis/rdar-6582778-basic-store.c b/test/Analysis/rdar-6582778-basic-store.c
index 9ec38ef7a5f0..a4850c133201 100644
--- a/test/Analysis/rdar-6582778-basic-store.c
+++ b/test/Analysis/rdar-6582778-basic-store.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
typedef const void * CFTypeRef;
typedef double CFTimeInterval;
diff --git a/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m
index 49ef7c381545..7230f21c08c3 100644
--- a/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m
+++ b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=basic %s -verify &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=region %s -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-constraints=basic -analyzer-store=basic %s -verify
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-constraints=basic -analyzer-store=region %s -verify
typedef struct Foo { int x; } Bar;
diff --git a/test/Analysis/rdar-7168531.m b/test/Analysis/rdar-7168531.m
index bdbd22d24e2c..6c34125d056c 100644
--- a/test/Analysis/rdar-7168531.m
+++ b/test/Analysis/rdar-7168531.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -triple i386-apple-darwin10 -analyzer-store=region &&
-// RUN: clang-cc -analyze -checker-cfref -triple i386-apple-darwin10 -analyzer-store=basic
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -triple i386-apple-darwin10 -analyzer-store=region
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -triple i386-apple-darwin10 -analyzer-store=basic
// Note that the target triple is important for this test case. It specifies that we use the
// fragile Objective-C ABI.
diff --git a/test/Analysis/refcnt_naming.m b/test/Analysis/refcnt_naming.m
index 2ce00b2a8cca..a4c290442a57 100644
--- a/test/Analysis/refcnt_naming.m
+++ b/test/Analysis/refcnt_naming.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
typedef const struct __CFString * CFStringRef;
typedef const struct __CFAllocator * CFAllocatorRef;
diff --git a/test/Analysis/region-1.m b/test/Analysis/region-1.m
index 68a375b7126c..6a8ae49bba4b 100644
--- a/test/Analysis/region-1.m
+++ b/test/Analysis/region-1.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=basic -verify %s
+// RUN: clang-cc -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
//
// This test case simply should not crash. It evaluates the logic of not
// using MemRegion::getRValueType in incorrect places.
@@ -89,3 +89,4 @@ Dos_CharacterRangeType = 0, Dos_LineRangeType = 1 }
symbol = [HancodeFett symbolFromClass:(JabaSCClass *) selectedClassifier];
}
}
+@end
diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m
index e27cfe758aaf..3eeebc4a8f0a 100644
--- a/test/Analysis/retain-release-gc-only.m
+++ b/test/Analysis/retain-release-gc-only.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify -fobjc-gc-only %s &&
+// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify -fobjc-gc-only %s
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -fobjc-gc-only -verify %s
//===----------------------------------------------------------------------===//
@@ -372,4 +372,4 @@ CFDateRef returnsRetainedCFDate() {
- (NSDate*) returnsNSRetained {
return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
}
-@end \ No newline at end of file
+@end
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index 879e8a0413b4..dfea2e7738d0 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -verify %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -verify %s
// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -verify %s
#if __has_feature(attribute_ns_returns_retained)
diff --git a/test/Analysis/security-syntax-checks.m b/test/Analysis/security-syntax-checks.m
index ebd7d172b5b4..bcdc65ebd459 100644
--- a/test/Analysis/security-syntax-checks.m
+++ b/test/Analysis/security-syntax-checks.m
@@ -30,6 +30,13 @@ void test_gets() {
gets(buff); // expected-warning{{Call to function 'gets' is extremely insecure as it can always result in a buffer overflow}}
}
+int getpw(unsigned int uid, char *buf);
+
+void test_getpw() {
+ char buff[1024];
+ getpw(2, buff); // expected-warning{{The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid().}}
+}
+
// <rdar://problem/6337132> CWE-273: Failure to Check Whether Privileges Were
// Dropped Successfully
typedef unsigned int __uint32_t;
diff --git a/test/Analysis/sizeofpointer.c b/test/Analysis/sizeofpointer.c
new file mode 100644
index 000000000000..e40c71857242
--- /dev/null
+++ b/test/Analysis/sizeofpointer.c
@@ -0,0 +1,8 @@
+// RUN: clang-cc -analyze -warn-sizeof-pointer -verify %s
+
+struct s {
+};
+
+int f(struct s *p) {
+ return sizeof(p); // expected-warning{{The code calls sizeof() on a pointer type. This can produce an unexpected result.}}
+}
diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c
index 0d7a70373c9a..f26e2f0c6352 100644
--- a/test/Analysis/stack-addr-ps.c
+++ b/test/Analysis/stack-addr-ps.c
@@ -1,8 +1,6 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
+// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
-#include <stdlib.h>
-
int* f1() {
int x = 0;
return &x; // expected-warning{{Address of stack memory associated with local variable 'x' returned.}} expected-warning{{address of stack memory associated with local variable 'x' returned}}
diff --git a/test/Analysis/uninit-msg-expr.m b/test/Analysis/uninit-msg-expr.m
index 5ec878ea3c37..c2b73668dd95 100644
--- a/test/Analysis/uninit-msg-expr.m
+++ b/test/Analysis/uninit-msg-expr.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
+// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
//===----------------------------------------------------------------------===//
diff --git a/test/Analysis/uninit-ps-rdar6145427.m b/test/Analysis/uninit-ps-rdar6145427.m
index 49eb26984a0b..d9e73188003f 100644
--- a/test/Analysis/uninit-ps-rdar6145427.m
+++ b/test/Analysis/uninit-ps-rdar6145427.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -verify -analyzer-store=basic -checker-cfref %s &&
+// RUN: clang-cc -analyze -verify -analyzer-store=basic -checker-cfref %s
// RUN: clang-cc -analyze -verify -analyzer-store=region -checker-cfref %s
// Delta-Debugging reduced preamble.
diff --git a/test/Analysis/uninit-vals-ps.c b/test/Analysis/uninit-vals-ps.c
index 759c7edbcc57..c8632a50300a 100644
--- a/test/Analysis/uninit-vals-ps.c
+++ b/test/Analysis/uninit-vals-ps.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
+// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
struct FPRec {
diff --git a/test/Analysis/uninit-vals.m b/test/Analysis/uninit-vals.m
index 7be247e7ca9e..6d1561eeb511 100644
--- a/test/Analysis/uninit-vals.m
+++ b/test/Analysis/uninit-vals.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
+// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
typedef unsigned int NSUInteger;
diff --git a/test/Analysis/unused-ivars.m b/test/Analysis/unused-ivars.m
index 9e9360da50c6..754799b2dbd8 100644
--- a/test/Analysis/unused-ivars.m
+++ b/test/Analysis/unused-ivars.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -warn-objc-unused-ivars %s -verify
+// RUN: clang-cc -fblocks -analyze -warn-objc-unused-ivars %s -verify
//===--- BEGIN: Delta-debugging reduced headers. --------------------------===//
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8b3c738ed78b..cd822f623a79 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -22,11 +22,19 @@ set(CLANG_TEST_DIRECTORIES
"SemaObjCXX"
"SemaTemplate")
+set(LLVM_SOURCE_DIR "${LLVM_MAIN_SRC_DIR}")
+set(LLVM_BINARY_DIR "${LLVM_BINARY_DIR}")
+set(LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}/%(build_config)s")
+set(LLVM_LIBS_DIR "${LLVM_BINARY_DIR}/lib/%(build_config)s")
+set(CLANG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
+set(CLANG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/..")
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
+
include(FindPythonInterp)
if(PYTHONINTERP_FOUND)
- get_target_triple(TARGET_TRIPLE)
- get_target_property(LLVM_TOOLS_PATH clang RUNTIME_OUTPUT_DIRECTORY)
- get_target_property(LLVM_LIBS_PATH clang LIBRARY_OUTPUT_DIRECTORY)
set(CLANG_TEST_EXTRA_ARGS)
if (MSVC OR XCODE)
set(CLANG_TEST_EXTRA_ARGS "--no-progress-bar")
@@ -34,18 +42,10 @@ if(PYTHONINTERP_FOUND)
foreach(testdir ${CLANG_TEST_DIRECTORIES})
add_custom_target(clang-test-${testdir}
- COMMAND sed -e "s#\@LLVM_SOURCE_DIR\@#${LLVM_MAIN_SRC_DIR}#"
- -e "s#\@LLVM_BINARY_DIR\@#${LLVM_BINARY_DIR}#"
- -e "s#\@LLVM_TOOLS_DIR\@#${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}#"
- -e "s#\@LLVM_LIBS_DIR\@#${LLVM_LIBS_PATH}/${CMAKE_CFG_INTDIR}#"
- -e "s#\@CLANG_SOURCE_DIR\@#${CMAKE_CURRENT_SOURCE_DIR}/..#"
- -e "s#\@CLANG_BINARY_DIR\@#${CMAKE_CURRENT_BINARY_DIR}/..#"
- -e "s#\@TARGET_TRIPLE\@#${TARGET_TRIPLE}#"
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in >
- ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
--param clang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ --param build_config=${CMAKE_CFG_INTDIR}
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}/${testdir}
DEPENDS clang clang-cc index-test c-index-test
@@ -53,36 +53,20 @@ if(PYTHONINTERP_FOUND)
endforeach()
add_custom_target(clang-test
- COMMAND sed -e "s#\@LLVM_SOURCE_DIR\@#${LLVM_MAIN_SRC_DIR}#"
- -e "s#\@LLVM_BINARY_DIR\@#${LLVM_BINARY_DIR}#"
- -e "s#\@LLVM_TOOLS_DIR\@#${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}#"
- -e "s#\@LLVM_LIBS_DIR\@#${LLVM_LIBS_PATH}/${CMAKE_CFG_INTDIR}#"
- -e "s#\@CLANG_SOURCE_DIR\@#${CMAKE_CURRENT_SOURCE_DIR}/..#"
- -e "s#\@CLANG_BINARY_DIR\@#${CMAKE_CURRENT_BINARY_DIR}/..#"
- -e "s#\@TARGET_TRIPLE\@#${TARGET_TRIPLE}#"
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in >
- ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
--param clang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ --param build_config=${CMAKE_CFG_INTDIR}
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS clang clang-cc index-test c-index-test
COMMENT "Running Clang regression tests")
add_custom_target(clang-c++tests
- COMMAND sed -e "s#\@LLVM_SOURCE_DIR\@#${LLVM_MAIN_SRC_DIR}#"
- -e "s#\@LLVM_BINARY_DIR\@#${LLVM_BINARY_DIR}#"
- -e "s#\@LLVM_TOOLS_DIR\@#${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}#"
- -e "s#\@LLVM_LIBS_DIR\@#${LLVM_LIBS_PATH}/${CMAKE_CFG_INTDIR}#"
- -e "s#\@CLANG_SOURCE_DIR\@#${CMAKE_CURRENT_SOURCE_DIR}/..#"
- -e "s#\@CLANG_BINARY_DIR\@#${CMAKE_CURRENT_BINARY_DIR}/..#"
- -e "s#\@TARGET_TRIPLE\@#${TARGET_TRIPLE}#"
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in >
- ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
--param clang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ --param build_config=${CMAKE_CFG_INTDIR}
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_SOURCE_DIR}/../utils/C++Tests
DEPENDS clang clang-cc index-test c-index-test
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.udir/p1.cpp b/test/CXX/basic/basic.lookup/basic.lookup.udir/p1.cpp
new file mode 100644
index 000000000000..04aef1e39e40
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.udir/p1.cpp
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// When looking up a namespace-name in a using-directive or
+// namespace-alias-definition, only namespace names are considered.
+
+struct ns1 {};
+void ns2();
+int ns3 = 0;
+
+namespace ns0 {
+ namespace ns1 {
+ struct test0 {};
+ }
+ namespace ns2 {
+ struct test1 {};
+ }
+ namespace ns3 {
+ struct test2 {};
+ }
+}
+
+using namespace ns0;
+
+namespace test3 = ns1;
+namespace test4 = ns2;
+namespace test5 = ns3;
+
+using namespace ns1;
+using namespace ns2;
+using namespace ns3;
+
+test0 a;
+test1 b;
+test2 c;
+
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp
new file mode 100644
index 000000000000..dd30d6ad4f98
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-cc -emit-llvm-only -verify %s
+
+// This lame little test was ripped straight from the standard.
+
+namespace {
+ int i; // expected-note {{candidate}}
+}
+void test0() { i++; }
+
+namespace A {
+ namespace {
+ int i; // expected-note {{candidate}}
+ int j;
+ }
+ void test1() { i++; }
+}
+
+using namespace A;
+
+void test2() {
+ i++; // expected-error {{reference to 'i' is ambiguous}}
+ A::i++;
+ j++;
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
new file mode 100644
index 000000000000..35e8c08a112f
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
@@ -0,0 +1,67 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// We have to avoid ADL for this test.
+
+template <unsigned N> class test {};
+
+class foo {};
+test<0> foo(foo); // expected-note {{candidate}}
+
+namespace Test0 {
+ class foo { int x; };
+ test<1> foo(class foo);
+
+ namespace A {
+ test<2> foo(class ::foo); // expected-note {{candidate}}
+
+ void test0() {
+ using ::foo;
+
+ class foo a;
+ test<0> _ = (foo)(a);
+ }
+
+ void test1() {
+ using Test0::foo;
+
+ class foo a;
+ test<1> _ = (foo)(a);
+ };
+
+ void test2() {
+ class ::foo a;
+
+ // Argument-dependent lookup is ambiguous between B:: and ::.
+ test<0> _0 = foo(a); // expected-error {{call to 'foo' is ambiguous}}
+
+ // But basic unqualified lookup is not.
+ test<2> _1 = (foo)(a);
+
+ class Test0::foo b;
+ test<2> _2 = (foo)(b); // expected-error {{incompatible type passing}}
+ }
+ }
+}
+
+namespace Test1 {
+ namespace A {
+ class a {};
+ }
+
+ namespace B {
+ typedef class {} b;
+ }
+
+ namespace C {
+ int c(); // expected-note {{target of using declaration}}
+ }
+
+ namespace D {
+ using typename A::a;
+ using typename B::b;
+ using typename C::c; // expected-error {{'typename' keyword used on a non-type}}
+
+ a _1 = A::a();
+ b _2 = B::b();
+ }
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp
new file mode 100644
index 000000000000..fbd205833cad
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp
@@ -0,0 +1,141 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// (this actually occurs before paragraph 1)
+namespace test0 {
+ namespace A {}
+ class B {
+ using namespace A; // expected-error {{'using namespace' is not allowed in classes}}
+ };
+}
+
+
+struct opaque0 {};
+struct opaque1 {};
+
+// Test that names appear as if in deepest common ancestor.
+namespace test1 {
+ namespace A {
+ namespace B {
+ opaque0 foo(); // expected-note {{candidate}}
+ }
+ }
+
+ namespace C {
+ opaque1 foo(); // expected-note {{candidate}}
+
+ opaque1 test() {
+ using namespace A::B;
+ return foo(); // C::foo
+ }
+ }
+
+ opaque1 test() {
+ using namespace A::B;
+ using namespace C;
+ return foo(); // expected-error {{call to 'foo' is ambiguous}}
+ }
+}
+
+// Same thing, but with the directives in namespaces.
+namespace test2 {
+ namespace A {
+ namespace B {
+ opaque0 foo(); // expected-note {{candidate}}
+ }
+ }
+
+ namespace C {
+ opaque1 foo(); // expected-note {{candidate}}
+
+ namespace test {
+ using namespace A::B;
+
+ opaque1 test() {
+ return foo(); // C::foo
+ }
+ }
+ }
+
+ namespace test {
+ using namespace A::B;
+ using namespace C;
+
+ opaque1 test() {
+ return foo(); // expected-error {{call to 'foo' is ambiguous}}
+ }
+ }
+}
+
+// Transitivity.
+namespace test3 {
+ namespace A {
+ namespace B {
+ opaque0 foo();
+ }
+ }
+ namespace C {
+ using namespace A;
+ }
+
+ opaque0 test0() {
+ using namespace C;
+ using namespace B;
+ return foo();
+ }
+
+ namespace D {
+ using namespace C;
+ }
+ namespace A {
+ opaque1 foo();
+ }
+
+ opaque1 test1() {
+ using namespace D;
+ return foo();
+ }
+}
+
+// Transitivity acts like synthetic using directives.
+namespace test4 {
+ namespace A {
+ namespace B {
+ opaque0 foo(); // expected-note {{candidate}}
+ }
+ }
+
+ namespace C {
+ using namespace A::B;
+ }
+
+ opaque1 foo(); // expected-note {{candidate}}
+
+ namespace A {
+ namespace D {
+ using namespace C;
+ }
+
+ opaque0 test() {
+ using namespace D;
+ return foo();
+ }
+ }
+
+ opaque0 test() {
+ using namespace A::D;
+ return foo(); // expected-error {{call to 'foo' is ambiguous}}
+ }
+}
+
+// Bug: using directives should be followed when parsing default
+// arguments in scoped declarations.
+class test5 {
+ int inc(int x);
+};
+namespace Test5 {
+ int default_x = 0;
+}
+using namespace Test5;
+int test5::inc(int x = default_x) {
+ return x+1;
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp
new file mode 100644
index 000000000000..a3c147db5ee2
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp
@@ -0,0 +1,44 @@
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+
+// Simple form
+int ar1[10];
+
+// Element type cannot be:
+// - (cv) void
+volatile void ar2[10]; // expected-error {{incomplete element type 'void volatile'}}
+// - a reference
+int& ar3[10]; // expected-error {{array of references}}
+// - a function type
+typedef void Fn();
+Fn ar4[10]; // expected-error {{array of functions}}
+// - an abstract class
+struct Abstract { virtual void fn() = 0; }; // expected-note {{pure virtual}}
+Abstract ar5[10]; // expected-error {{abstract class}}
+
+// If we have a size, it must be greater than zero.
+int ar6[-1]; // expected-error {{array size is negative}}
+int ar7[0u]; // expected-warning {{zero size arrays are an extension}}
+
+// An array with unknown bound is incomplete.
+int ar8[]; // expected-error {{needs an explicit size or an initializer}}
+// So is an array with an incomplete element type.
+struct Incomplete; // expected-note {{forward declaration}}
+Incomplete ar9[10]; // expected-error {{incomplete type}}
+// Neither of which should be a problem in situations where no complete type
+// is required. (PR5048)
+void fun(int p1[], Incomplete p2[10]);
+extern int ear1[];
+extern Incomplete ear2[10];
+
+// cv migrates to element type
+typedef const int cint;
+extern cint car1[10];
+typedef int intar[10];
+// thus this is a valid redeclaration
+extern const intar car1;
+
+// Check that instantiation works properly when the element type is a template.
+template <typename T> struct S {
+ typename T::type x; // expected-error {{has no members}}
+};
+S<int> ar10[10]; // expected-note {{requested here}}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
index bbfaf909392a..4b1582840c39 100644
--- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
@@ -52,4 +52,4 @@ namespace N1 {
{
f2(6); // okay
}
-} \ No newline at end of file
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp
index 6f71978c4e46..01fa6ac35548 100644
--- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp
@@ -1,3 +1,3 @@
// RUN: clang-cc -fsyntax-only -verify %s
void f(int) { } // expected-note {{previous definition is here}}
-void f(const int) { } // expected-error {{redefinition of 'f'}} \ No newline at end of file
+void f(const int) { } // expected-error {{redefinition of 'f'}}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp
index 101d75fc0f48..5f9a5345cf1c 100644
--- a/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %t
+// RUN: clang-cc -fsyntax-only -verify %s
class A {
public:
int& i;
@@ -20,7 +20,7 @@ void f() {
a.*&A::s = 10; // expected-error{{right hand operand to .* has non pointer-to-member type 'int *'}}
a.*&A::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}}
- ft(a); // expected-note{{in instantiation of function template specialization 'ft' requested here}}
+ ft(a); // expected-note{{in instantiation of function template specialization 'ft<class A>' requested here}}
void A::*p = 0; // expected-error{{'p' declared as a member pointer to void}}
}
diff --git a/test/CXX/expr/expr.unary/expr.delete/p5.cpp b/test/CXX/expr/expr.unary/expr.delete/p5.cpp
new file mode 100644
index 000000000000..91e77bcb8bf7
--- /dev/null
+++ b/test/CXX/expr/expr.unary/expr.delete/p5.cpp
@@ -0,0 +1,34 @@
+// RUN: clang-cc -verify %s
+
+// If the object being deleted has incomplete class type at the point of
+// deletion and the complete class has a non-trivial destructor or a
+// deallocation function, the behavior is undefined.
+
+// The trivial case.
+class T0; // expected-note {{forward declaration}}
+void f0(T0 *a) { delete a; } // expected-warning {{deleting pointer to incomplete type}}
+class T0 { ~T0(); };
+
+// The trivial case, inside a template instantiation.
+template<typename T>
+class T1_A { T *x; ~T1_A() { delete x; } }; // expected-warning {{deleting pointer to incomplete type}}
+class T1_B; // expected-note {{forward declaration}}
+void f0() { T1_A<T1_B> x; } // expected-note {{in instantiation of member function}}
+
+// This case depends on when we check T2_C::f0.
+class T2_A;
+template<typename T>
+struct T2_B { void f0(T *a) { delete a; } };
+struct T2_C { T2_B<T2_A> x; void f0(T2_A *a) { x.f0(a); } };
+void f0(T2_A *a) { T2_C x; x.f0(a); }
+class T2_A { };
+
+// An alternate version of the same.
+//
+// FIXME: Revisit this case when we have access control.
+class T3_A;
+template<typename T>
+struct T3_B { void f0(T *a) { delete a; } };
+struct T3_C { T3_B<T3_A> x; void f0(T3_A *a) { x.f0(a); } };
+void f0(T3_A *a) { T3_C x; x.f0(a); }
+class T3_A { private: ~T3_A(); };
diff --git a/test/CXX/special/class.free/p1.cpp b/test/CXX/special/class.free/p1.cpp
new file mode 100644
index 000000000000..bf99a2782bd5
--- /dev/null
+++ b/test/CXX/special/class.free/p1.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+#include <stddef.h>
+
+struct A {
+ void *operator new(size_t) {
+ return this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ }
+ void *operator new[](size_t) {
+ return this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ }
+};
diff --git a/test/CXX/special/class.free/p6.cpp b/test/CXX/special/class.free/p6.cpp
new file mode 100644
index 000000000000..8334817ca2b5
--- /dev/null
+++ b/test/CXX/special/class.free/p6.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+#include <stddef.h>
+
+struct A {
+ void operator delete(size_t) {
+ (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ }
+ void operator delete[](void*) {
+ (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+ }
+};
diff --git a/test/CXX/temp/temp.param/p1.cpp b/test/CXX/temp/temp.param/p1.cpp
index a6638b4f60f2..676bffe31dc5 100644
--- a/test/CXX/temp/temp.param/p1.cpp
+++ b/test/CXX/temp/temp.param/p1.cpp
@@ -1,4 +1,4 @@
// Suppress 'no run line' failure.
-// RUN: true
+// RUN: echo ok
// Paragraph 1 is descriptive, and therefore requires no tests.
diff --git a/test/CXX/temp/temp.param/p12.cpp b/test/CXX/temp/temp.param/p12.cpp
index 5511224ebe94..3864fbeaa11e 100644
--- a/test/CXX/temp/temp.param/p12.cpp
+++ b/test/CXX/temp/temp.param/p12.cpp
@@ -34,4 +34,6 @@ template<int N,
// Check validity of default arguments
template<template<class, int> class // expected-note{{previous template template parameter is here}}
= Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
- class C1;
+ class C1 {};
+
+C1<> c1; // expected-note{{while checking a default template argument}}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
index 33fb93bacfaf..de05a926338c 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
@@ -10,4 +10,4 @@ namespace N {
template<> class X<char*> { /* ... */ }; // OK: X is a template
-} \ No newline at end of file
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
index 8d91068f9b99..ad0d50621367 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
@@ -12,7 +12,7 @@ struct X { // expected-note{{here}}
void g() { }
- struct Inner {
+ struct Inner { // expected-error{{implicit default}}
T value; // expected-note {{member is declared here}}
};
@@ -26,8 +26,7 @@ IntHolder &test_X_IntHolderInt(X<IntHolder, int> xih) {
xih.g(); // okay
xih.f(); // expected-note{{instantiation}}
- // FIXME: diagnostic here has incorrect reason (PR5154)
- X<IntHolder, int>::Inner inner; // expected-error{{implicit default}}
+ X<IntHolder, int>::Inner inner; // expected-note {{first required here}}
return X<IntHolder, int>::value; // expected-note{{instantiation}}
}
diff --git a/test/CodeCompletion/call.cpp b/test/CodeCompletion/call.cpp
index 90bf82bff307..8c7bf83e2a3a 100644
--- a/test/CodeCompletion/call.cpp
+++ b/test/CodeCompletion/call.cpp
@@ -17,12 +17,11 @@ void f();
void test() {
f(Y(), 0, 0);
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: f(struct N::Y y, <#int ZZ#>)
// CHECK-CC1-NEXT: f(int i, <#int j#>, int k)
// CHECK-CC1-NEXT: f(float x, <#float y#>)
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CC2 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CC2 %s
// CHECK-CC2-NOT: f(struct N::Y y, int ZZ)
// CHECK-CC2: f(int i, int j, <#int k#>)
- // RUN: true
}
diff --git a/test/CodeCompletion/enum-switch-case-qualified.cpp b/test/CodeCompletion/enum-switch-case-qualified.cpp
index 223aca8b9323..3e8d75d940d7 100644
--- a/test/CodeCompletion/enum-switch-case-qualified.cpp
+++ b/test/CodeCompletion/enum-switch-case-qualified.cpp
@@ -21,8 +21,7 @@ namespace M {
void test(enum N::C::Color color) {
switch (color) {
case
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:23:8 %s -o - | FileCheck -check-prefix=CC1 %s &&
- // RUN: true
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:23:8 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: Blue : 0 : N::C::Blue
// CHECK-CC1-NEXT: Green : 0 : N::C::Green
// CHECK-CC1-NEXT: Indigo : 0 : N::C::Indigo
diff --git a/test/CodeCompletion/enum-switch-case.c b/test/CodeCompletion/enum-switch-case.c
index d8bb5e8ca474..b7a3676170bf 100644
--- a/test/CodeCompletion/enum-switch-case.c
+++ b/test/CodeCompletion/enum-switch-case.c
@@ -19,11 +19,10 @@ void test(enum Color color) {
case Green:
break;
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:10 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:10 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: Blue : 0
// CHECK-CC1-NEXT: Green : 0
// CHECK-CC1-NEXT: Indigo : 0
// CHECK-CC1-NEXT: Orange : 0
// CHECK-CC1-NEXT: Violet : 0
- // RUN: true
diff --git a/test/CodeCompletion/enum-switch-case.cpp b/test/CodeCompletion/enum-switch-case.cpp
index 7a388fce0e39..3a010a83dee5 100644
--- a/test/CodeCompletion/enum-switch-case.cpp
+++ b/test/CodeCompletion/enum-switch-case.cpp
@@ -19,11 +19,10 @@ void test(enum N::Color color) {
break;
case
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:21:8 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:21:8 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: Blue : 0 : N::Blue
// CHECK-CC1-NEXT: Green : 0 : N::Green
// CHECK-CC1-NEXT: Indigo : 0 : N::Indigo
// CHECK-CC1-NEXT: Orange : 0 : N::Orange
// CHECK-CC1-NEXT: Violet : 0 : N::Violet
- // RUN: true
diff --git a/test/CodeCompletion/function-templates.cpp b/test/CodeCompletion/function-templates.cpp
index 52cba71bd2f9..d291bbe12bad 100644
--- a/test/CodeCompletion/function-templates.cpp
+++ b/test/CodeCompletion/function-templates.cpp
@@ -8,8 +8,7 @@ namespace std {
void f() {
std::
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:8 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:8 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: dyn_cast<<#class X#>>(<#Y *Val#>)
// CHECK-CC1: sort(<#RandomAccessIterator first#>, <#RandomAccessIterator last#>)
- // RUN: true
diff --git a/test/CodeCompletion/functions.cpp b/test/CodeCompletion/functions.cpp
index 2e1bc6edf8c4..85292e4d3076 100644
--- a/test/CodeCompletion/functions.cpp
+++ b/test/CodeCompletion/functions.cpp
@@ -3,7 +3,6 @@ void f(float x, float y...);
void test() {
::
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:5:5 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:5:5 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: f(<#int i#>{#, <#int j#>{#, <#int k#>#}#})
// CHECK-CC1: f(<#float x#>, <#float y#><#, ...#>)
- // RUN: true
diff --git a/test/CodeCompletion/macros.c b/test/CodeCompletion/macros.c
index d5c1f8f17fce..20d26f2f773a 100644
--- a/test/CodeCompletion/macros.c
+++ b/test/CodeCompletion/macros.c
@@ -13,9 +13,9 @@ struct Point {
};
void test(struct Point *p) {
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:17:14 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-macros -code-completion-at=%s:17:14 %s -o - | FileCheck -check-prefix=CC1 %s
switch (p->IDENTITY(color)) {
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC2 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-macros -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC2 %s
case
}
// CC1: color
@@ -33,5 +33,4 @@ void test(struct Point *p) {
// CC2: FOO
// CC2: IDENTITY(<#X#>)
// CC2: WIBBLE
- // RUN: true
}
diff --git a/test/CodeCompletion/member-access.c b/test/CodeCompletion/member-access.c
index 1e8e5630981f..c9ac58f295d4 100644
--- a/test/CodeCompletion/member-access.c
+++ b/test/CodeCompletion/member-access.c
@@ -6,8 +6,7 @@ struct Point {
void test(struct Point *p) {
p->
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:8:6 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:8:6 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: x
// CHECK-CC1: y
// CHECK-CC1: z
- // RUN: true
diff --git a/test/CodeCompletion/member-access.cpp b/test/CodeCompletion/member-access.cpp
index b810366209f5..e445b4503aa3 100644
--- a/test/CodeCompletion/member-access.cpp
+++ b/test/CodeCompletion/member-access.cpp
@@ -27,7 +27,7 @@ public:
void test(const Proxy &p) {
p->
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: member1 : 0 : [#Base1::#]member1
// CHECK-CC1: member1 : 0 : [#Base2::#]member1
// CHECK-CC1: member2 : 0 : [#Base1::#]member2
@@ -39,5 +39,4 @@ void test(const Proxy &p) {
// CHECK-CC1: memfun3 : 0 : memfun3(<#int#>)
// CHECK-CC1: Base1 : 0 : Base1::
// CHECK-CC1: memfun1 : 0 (Hidden) : Base2::memfun1(<#int#>)
- // RUN: true
diff --git a/test/CodeCompletion/namespace-alias.cpp b/test/CodeCompletion/namespace-alias.cpp
index 0fa2ec20209c..c1f34178c3ec 100644
--- a/test/CodeCompletion/namespace-alias.cpp
+++ b/test/CodeCompletion/namespace-alias.cpp
@@ -11,11 +11,10 @@ namespace N2 {
namespace I1 { }
namespace New =
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:13:18 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:13:18 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: I1 : 1
// CHECK-CC1: I4 : 1
// CHECK-CC1: I5 : 1
// CHECK-CC1: N2 : 3
// CHECK-CC1-NEXT: N4 : 3
- // RUN: true
diff --git a/test/CodeCompletion/namespace.cpp b/test/CodeCompletion/namespace.cpp
index d4ed639f8a05..ff90b85b5a57 100644
--- a/test/CodeCompletion/namespace.cpp
+++ b/test/CodeCompletion/namespace.cpp
@@ -8,8 +8,7 @@ namespace N2 {
namespace I1 { }
namespace
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:12 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:12 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: I1 : 0
// CHECK-CC1-NEXT: I5 : 0
- // RUN: true
diff --git a/test/CodeCompletion/nested-name-specifier.cpp b/test/CodeCompletion/nested-name-specifier.cpp
index 0cc5a19421c7..8da7c37d95e9 100644
--- a/test/CodeCompletion/nested-name-specifier.cpp
+++ b/test/CodeCompletion/nested-name-specifier.cpp
@@ -10,9 +10,8 @@ namespace N {
}
N::
-// RUN: clang-cc -fsyntax-only -code-completion-at=%s:12:4 %s -o - | FileCheck -check-prefix=CC1 %s &&
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s:12:4 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: A : 0
// CHECK-CC1: B : 0
// CHECK-CC1: M : 0
-// RUN: true
diff --git a/test/CodeCompletion/objc-message.m b/test/CodeCompletion/objc-message.m
new file mode 100644
index 000000000000..d16a745b71f5
--- /dev/null
+++ b/test/CodeCompletion/objc-message.m
@@ -0,0 +1,35 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+@protocol FooTestProtocol
++ protocolClassMethod;
+- protocolInstanceMethod;
+@end
+@interface Foo <FooTestProtocol> {
+ void *isa;
+}
++ (int)classMethod1:a withKeyword:b;
++ (void)classMethod2;
++ new;
+- instanceMethod1;
+@end
+
+@interface Foo (FooTestCategory)
++ categoryClassMethod;
+- categoryInstanceMethod;
+@end
+
+void func() {
+ Foo *obj = [Foo new];
+ [obj xx];
+}
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s:23:19 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: categoryClassMethod : 0
+// CHECK-CC1: classMethod1:withKeyword: : 0
+// CHECK-CC1: classMethod2 : 0
+// CHECK-CC1: new : 0
+// CHECK-CC1: protocolClassMethod : 0
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s:24:8 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: categoryInstanceMethod : 0
+// CHECK-CC2: instanceMethod1 : 0
+// CHECK-CC2: protocolInstanceMethod : 0
diff --git a/test/CodeCompletion/operator.cpp b/test/CodeCompletion/operator.cpp
index a3950f6b8913..20ba5ba3fbc8 100644
--- a/test/CodeCompletion/operator.cpp
+++ b/test/CodeCompletion/operator.cpp
@@ -8,11 +8,10 @@ void f() {
typedef float Float;
operator
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:11 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:11 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: Float : 0
// CHECK-CC1: + : 0
// CHECK-CC1: short : 0
// CHECK-CC1: Integer : 2
// CHECK-CC1: T : 2
// CHECK-CC1: N : 6
- // RUN: true
diff --git a/test/CodeCompletion/ordinary-name.c b/test/CodeCompletion/ordinary-name.c
index 586e2b371bd7..680d6dc989c7 100644
--- a/test/CodeCompletion/ordinary-name.c
+++ b/test/CodeCompletion/ordinary-name.c
@@ -4,9 +4,8 @@ typedef struct t TYPEDEF;
void foo() {
int y;
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:6:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:6:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: y : 0
// CHECK-CC1: foo : 2
// CHECK-NOT-CC1: y : 2
// CHECK-CC1-NEXT: TYPEDEF : 2
- // RUN: true
diff --git a/test/CodeCompletion/property.m b/test/CodeCompletion/property.m
index 7f2321ee1395..184519b408fa 100644
--- a/test/CodeCompletion/property.m
+++ b/test/CodeCompletion/property.m
@@ -6,7 +6,7 @@
}
@property(copy) Foo *myprop;
@property(retain, nonatomic) id xx;
-// RUN: clang-cc -fsyntax-only -code-completion-at=%s:7:11 %s -o - | FileCheck -check-prefix=CC1 %s &&
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s:7:11 %s -o - | FileCheck -check-prefix=CC1 %s
// CC1: assign
// CC1-NEXT: copy
// CC1-NEXT: getter
diff --git a/test/CodeCompletion/tag.c b/test/CodeCompletion/tag.c
index e7250f540c4f..6d9c1eabd561 100644
--- a/test/CodeCompletion/tag.c
+++ b/test/CodeCompletion/tag.c
@@ -7,7 +7,6 @@ void X();
void test() {
enum X { x };
enum
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:9:7 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:9:7 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: X : 0
// CHECK-CC1: Y : 2
- // RUN: true
diff --git a/test/CodeCompletion/tag.cpp b/test/CodeCompletion/tag.cpp
index b00ff1fabdaa..17c9707db1a3 100644
--- a/test/CodeCompletion/tag.cpp
+++ b/test/CodeCompletion/tag.cpp
@@ -15,7 +15,7 @@ namespace N {
void test() {
class
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:17:10 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:17:10 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: Y : 2
// CHECK-CC1: Z : 2
// CHECK-CC1: A : 4
@@ -23,4 +23,3 @@ namespace N {
// CHECK-CC1: Y : 4
// CHECK-CC1: M : 9 : M::
// CHECK-CC1: N : 9 : N::
- // RUN: true
diff --git a/test/CodeCompletion/templates.cpp b/test/CodeCompletion/templates.cpp
index 22cca65bea98..d35e0bb8dcde 100644
--- a/test/CodeCompletion/templates.cpp
+++ b/test/CodeCompletion/templates.cpp
@@ -8,10 +8,9 @@ namespace std {
void f() {
std::
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:8 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:10:8 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: allocator<<#typename T#>>
// CHECK-CC1: vector<<#typename T#>{#, <#typename Alloc#>#}>
- // RUN: true
diff --git a/test/CodeCompletion/truncation.c b/test/CodeCompletion/truncation.c
index b72aa7facf79..5af3c4b6d6c9 100644
--- a/test/CodeCompletion/truncation.c
+++ b/test/CodeCompletion/truncation.c
@@ -2,11 +2,10 @@
struct
-// RUN: clang-cc -fsyntax-only -code-completion-at=%s.h:4:8 -o - %s | FileCheck -check-prefix=CC1 %s &&
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s.h:4:8 -o - %s | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: X : 1
// CHECK-CC1-NEXT: Y : 1
-// RUN: clang-cc -fsyntax-only -code-completion-at=%s:3:8 -o - %s | FileCheck -check-prefix=CC2 %s &&
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s:3:8 -o - %s | FileCheck -check-prefix=CC2 %s
// CHECK-CC2: X : 1
// CHECK-CC2: Xa : 1
// CHECK-CC2: Y : 1
-// RUN: true
diff --git a/test/CodeCompletion/using-namespace.cpp b/test/CodeCompletion/using-namespace.cpp
index a332b880074e..57383d5db427 100644
--- a/test/CodeCompletion/using-namespace.cpp
+++ b/test/CodeCompletion/using-namespace.cpp
@@ -12,10 +12,9 @@ namespace N2 {
void foo() {
using namespace
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:14:20 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:14:20 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: I1 : 2
// CHECK-CC1: I4 : 2
// CHECK-CC1: I5 : 2
// CHECK-CC1: N2 : 4
// CHECK-CC1-NEXT: N4 : 4
- // RUN: true
diff --git a/test/CodeCompletion/using.cpp b/test/CodeCompletion/using.cpp
index 57b3aa7880a2..305afda2e6dd 100644
--- a/test/CodeCompletion/using.cpp
+++ b/test/CodeCompletion/using.cpp
@@ -14,12 +14,11 @@ namespace N2 {
int N3;
using
- // RUN: clang-cc -fsyntax-only -code-completion-at=%s:16:10 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:16:10 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: I1 : 2
// CHECK-CC1: I4 : 2
// CHECK-CC1: I5 : 2
// CHECK-CC1: N2 : 4
// CHECK-CC1: N3 : 4
// CHECK-CC1-NEXT: N4 : 4
- // RUN: true
diff --git a/test/CodeGen/2008-07-17-no-emit-on-error.c b/test/CodeGen/2008-07-17-no-emit-on-error.c
index 51ba2b45d063..fbff54149bcc 100644
--- a/test/CodeGen/2008-07-17-no-emit-on-error.c
+++ b/test/CodeGen/2008-07-17-no-emit-on-error.c
@@ -1,5 +1,5 @@
-// RUN: rm -f %t1.bc &&
-// RUN: not clang-cc %s -emit-llvm-bc -o %t1.bc &&
+// RUN: rm -f %t1.bc
+// RUN: not clang-cc %s -emit-llvm-bc -o %t1.bc
// RUN: not test -f %t1.bc
void f() {
diff --git a/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c b/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c
index 348ea75ea295..db3c4b25d375 100644
--- a/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c
+++ b/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c
@@ -9,4 +9,4 @@ struct et7 {
};
// CHECK: @yv7 = global
-// CHECK: i8 52, \ No newline at end of file
+// CHECK: i8 52,
diff --git a/test/CodeGen/2008-07-29-override-alias-decl.c b/test/CodeGen/2008-07-29-override-alias-decl.c
index 872950029618..18e8982832e0 100644
--- a/test/CodeGen/2008-07-29-override-alias-decl.c
+++ b/test/CodeGen/2008-07-29-override-alias-decl.c
@@ -2,10 +2,10 @@
int x() { return 1; }
-// CHECK: %retval = alloca i32
-// CHECK: store i32 1, i32* %retval
-// CHECK: %0 = load i32* %retval
-// CHECK: ret i32 %0
+// CHECK: [[retval:%.*]] = alloca i32
+// CHECK: store i32 1, i32* [[retval]]
+// CHECK: [[load:%.*]] = load i32* [[retval]]
+// CHECK: ret i32 [[load]]
int f() __attribute__((weak, alias("x")));
@@ -17,9 +17,9 @@ int h() {
return f();
}
-// CHECK: %retval = alloca i32
-// CHECK: %call = call i32 (...)* @f()
-// CHECK: store i32 %call, i32* %retval
-// CHECK: %0 = load i32* %retval
-// CHECK: ret i32 %0
+// CHECK: [[retval:%.*]] = alloca i32
+// CHECK: [[call:%.*]] = call i32 (...)* @f()
+// CHECK: store i32 [[call]], i32* [[retval]]
+// CHECK: [[load:%.*]] = load i32* [[retval]]
+// CHECK: ret i32 [[load]]
diff --git a/test/CodeGen/2008-07-30-implicit-initialization.c b/test/CodeGen/2008-07-30-implicit-initialization.c
index 2f4c14eb728b..9cd530045bca 100644
--- a/test/CodeGen/2008-07-30-implicit-initialization.c
+++ b/test/CodeGen/2008-07-30-implicit-initialization.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt --std-compile-opts | llvm-dis > %t &&
-// RUN: grep "ret i32" %t | count 2 &&
+// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt --std-compile-opts | llvm-dis > %t
+// RUN: grep "ret i32" %t | count 2
// RUN: grep "ret i32 0" %t | count 2
// <rdar://problem/6113085>
diff --git a/test/CodeGen/2008-07-31-asm-labels.c b/test/CodeGen/2008-07-31-asm-labels.c
index f114f65eded2..d2dcc04bf584 100644
--- a/test/CodeGen/2008-07-31-asm-labels.c
+++ b/test/CodeGen/2008-07-31-asm-labels.c
@@ -1,10 +1,10 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
-// RUN: grep "@pipe()" %t | count 0 &&
-// RUN: grep '_thisIsNotAPipe' %t | count 3 &&
-// RUN: grep 'g0' %t | count 0 &&
-// RUN: grep '_renamed' %t | count 2 &&
-// RUN: clang-cc -DUSE_DEF -emit-llvm -o %t %s &&
-// RUN: grep "@pipe()" %t | count 0 &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: grep "@pipe()" %t | count 0
+// RUN: grep '_thisIsNotAPipe' %t | count 3
+// RUN: grep 'g0' %t | count 0
+// RUN: grep '_renamed' %t | count 2
+// RUN: clang-cc -DUSE_DEF -emit-llvm -o %t %s
+// RUN: grep "@pipe()" %t | count 0
// RUN: grep '_thisIsNotAPipe' %t | count 3
// <rdr://6116729>
diff --git a/test/CodeGen/2009-10-20-GlobalDebug.c b/test/CodeGen/2009-10-20-GlobalDebug.c
index eea3fb5307b4..fddc76c14da8 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_MIPS_linkage_name
+// CHECK: asciz "global" ## DW_AT_name
int main() { return 0;}
diff --git a/test/CodeGen/PR2001-bitfield-reload.c b/test/CodeGen/PR2001-bitfield-reload.c
index 797b494cf823..1fef3c56b53d 100644
--- a/test/CodeGen/PR2001-bitfield-reload.c
+++ b/test/CodeGen/PR2001-bitfield-reload.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt --std-compile-opts | llvm-dis > %t &&
-// RUN: grep "ret i32" %t | count 1 &&
+// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt --std-compile-opts | llvm-dis > %t
+// RUN: grep "ret i32" %t | count 1
// RUN: grep "ret i32 1" %t | count 1
// PR2001
diff --git a/test/CodeGen/PR3589-freestanding-libcalls.c b/test/CodeGen/PR3589-freestanding-libcalls.c
index 90b5fff1620f..14608137188e 100644
--- a/test/CodeGen/PR3589-freestanding-libcalls.c
+++ b/test/CodeGen/PR3589-freestanding-libcalls.c
@@ -1,8 +1,8 @@
-// RUN: clang-cc -emit-llvm %s -o - | grep 'declare i32 @printf' | count 1 &&
-// RUN: clang-cc -O2 -emit-llvm %s -o - | grep 'declare i32 @puts' | count 1 &&
+// RUN: clang-cc -emit-llvm %s -o - | grep 'declare i32 @printf' | count 1
+// RUN: clang-cc -O2 -emit-llvm %s -o - | grep 'declare i32 @puts' | count 1
// RUN: clang-cc -ffreestanding -O2 -emit-llvm %s -o - | grep 'declare i32 @puts' | count 0
-#include <stdio.h>
+int printf(const char *, ...);
void f0() {
printf("hello\n");
diff --git a/test/CodeGen/PR3613-static-decl.c b/test/CodeGen/PR3613-static-decl.c
index 208358130000..a9dc74458926 100644
--- a/test/CodeGen/PR3613-static-decl.c
+++ b/test/CodeGen/PR3613-static-decl.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s
// RUN: grep '@g0 = internal global %.truct.s0 { i32 3 }' %t | count 1
struct s0 {
diff --git a/test/CodeGen/PR4611-bitfield-layout.c b/test/CodeGen/PR4611-bitfield-layout.c
index 83ce4ffdbd6d..bc514bf4dfe2 100644
--- a/test/CodeGen/PR4611-bitfield-layout.c
+++ b/test/CodeGen/PR4611-bitfield-layout.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t &&
+// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t
// RUN: grep "struct.object_entry = type { i8, \[2 x i8\], i8 }" %t
struct object_entry {
diff --git a/test/CodeGen/address-space-field1.c b/test/CodeGen/address-space-field1.c
index f8ec83ca71cf..b041cf55d0b0 100644
--- a/test/CodeGen/address-space-field1.c
+++ b/test/CodeGen/address-space-field1.c
@@ -1,23 +1,22 @@
// RUN: clang-cc -emit-llvm < %s -o - | FileCheck %s
// CHECK:%struct.S = type { i32, i32 }
// CHECK:define void @test_addrspace(%struct.S addrspace(1)* %p1, %struct.S addrspace(2)* %p2) nounwind
-// CHECK:entry:
-// CHECK: %p1.addr = alloca %struct.S addrspace(1)* ; <%struct.S addrspace(1)**> [#uses=3]
-// CHECK: %p2.addr = alloca %struct.S addrspace(2)* ; <%struct.S addrspace(2)**> [#uses=3]
-// CHECK: store %struct.S addrspace(1)* %p1, %struct.S addrspace(1)** %p1.addr
-// CHECK: store %struct.S addrspace(2)* %p2, %struct.S addrspace(2)** %p2.addr
-// CHECK: %tmp = load %struct.S addrspace(2)** %p2.addr ; <%struct.S addrspace(2)*> [#uses=1]
-// CHECK: %tmp1 = getelementptr inbounds %struct.S addrspace(2)* %tmp, i32 0, i32 1 ; <i32 addrspace(2)*> [#uses=1]
-// CHECK: %tmp2 = load i32 addrspace(2)* %tmp1 ; <i32> [#uses=1]
-// CHECK: %tmp3 = load %struct.S addrspace(1)** %p1.addr ; <%struct.S addrspace(1)*> [#uses=1]
-// CHECK: %tmp4 = getelementptr inbounds %struct.S addrspace(1)* %tmp3, i32 0, i32 0 ; <i32 addrspace(1)*> [#uses=1]
-// CHECK: store i32 %tmp2, i32 addrspace(1)* %tmp4
-// CHECK: %tmp5 = load %struct.S addrspace(2)** %p2.addr ; <%struct.S addrspace(2)*> [#uses=1]
-// CHECK: %tmp6 = getelementptr inbounds %struct.S addrspace(2)* %tmp5, i32 0, i32 0 ; <i32 addrspace(2)*> [#uses=1]
-// CHECK: %tmp7 = load i32 addrspace(2)* %tmp6 ; <i32> [#uses=1]
-// CHECK: %tmp8 = load %struct.S addrspace(1)** %p1.addr ; <%struct.S addrspace(1)*> [#uses=1]
-// CHECK: %tmp9 = getelementptr inbounds %struct.S addrspace(1)* %tmp8, i32 0, i32 1 ; <i32 addrspace(1)*> [#uses=1]
-// CHECK: store i32 %tmp7, i32 addrspace(1)* %tmp9
+// CHECK: [[p1addr:%.*]] = alloca %struct.S addrspace(1)* ; <%struct.S addrspace(1)**> [#uses=3]
+// CHECK: [[p2addr:%.*]] = alloca %struct.S addrspace(2)* ; <%struct.S addrspace(2)**> [#uses=3]
+// CHECK: store %struct.S addrspace(1)* %p1, %struct.S addrspace(1)** [[p1addr]]
+// CHECK: store %struct.S addrspace(2)* %p2, %struct.S addrspace(2)** [[p2addr]]
+// CHECK: [[t0:%.*]] = load %struct.S addrspace(2)** [[p2addr]] ; <%struct.S addrspace(2)*> [#uses=1]
+// CHECK: [[t1:%.*]] = getelementptr inbounds %struct.S addrspace(2)* [[t0]], i32 0, i32 1 ; <i32 addrspace(2)*> [#uses=1]
+// CHECK: [[t2:%.*]] = load i32 addrspace(2)* [[t1]] ; <i32> [#uses=1]
+// CHECK: [[t3:%.*]] = load %struct.S addrspace(1)** [[p1addr]] ; <%struct.S addrspace(1)*> [#uses=1]
+// CHECK: [[t4:%.*]] = getelementptr inbounds %struct.S addrspace(1)* [[t3]], i32 0, i32 0 ; <i32 addrspace(1)*> [#uses=1]
+// CHECK: store i32 [[t2]], i32 addrspace(1)* [[t4]]
+// CHECK: [[t5:%.*]] = load %struct.S addrspace(2)** [[p2addr]] ; <%struct.S addrspace(2)*> [#uses=1]
+// CHECK: [[t6:%.*]] = getelementptr inbounds %struct.S addrspace(2)* [[t5]], i32 0, i32 0 ; <i32 addrspace(2)*> [#uses=1]
+// CHECK: [[t7:%.*]] = load i32 addrspace(2)* [[t6]] ; <i32> [#uses=1]
+// CHECK: [[t8:%.*]] = load %struct.S addrspace(1)** [[p1addr]] ; <%struct.S addrspace(1)*> [#uses=1]
+// CHECK: [[t9:%.*]] = getelementptr inbounds %struct.S addrspace(1)* [[t8]], i32 0, i32 1 ; <i32 addrspace(1)*> [#uses=1]
+// CHECK: store i32 [[t7]], i32 addrspace(1)* [[t9]]
// CHECK: ret void
// CHECK:}
diff --git a/test/CodeGen/address-space.c b/test/CodeGen/address-space.c
index 3b6a8e654167..8536f161533b 100644
--- a/test/CodeGen/address-space.c
+++ b/test/CodeGen/address-space.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -emit-llvm < %s | grep '@foo.*global.*addrspace(1)' &&
-// RUN: clang-cc -emit-llvm < %s | grep '@ban.*global.*addrspace(1)' &&
-// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(1)' | count 2 &&
-// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(2).. @A' &&
+// RUN: clang-cc -emit-llvm < %s | grep '@foo.*global.*addrspace(1)'
+// RUN: clang-cc -emit-llvm < %s | grep '@ban.*global.*addrspace(1)'
+// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(1)' | count 2
+// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(2).. @A'
// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(2).. @B'
int foo __attribute__((address_space(1)));
diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c
index b0c71fbdfca4..f8836e6f605f 100644
--- a/test/CodeGen/alias.c
+++ b/test/CodeGen/alias.c
@@ -1,8 +1,8 @@
-// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s &&
-// RUN: grep '@g0 = common global i32 0' %t &&
-// RUN: grep '@f1 = alias void ()\* @f0' %t &&
-// RUN: grep '@g1 = alias i32\* @g0' %t &&
-// RUN: grep 'define void @f0() nounwind {' %t &&
+// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: grep '@g0 = common global i32 0' %t
+// RUN: grep '@f1 = alias void ()\* @f0' %t
+// RUN: grep '@g1 = alias i32\* @g0' %t
+// RUN: grep 'define void @f0() nounwind {' %t
void f0(void) { }
extern void f1(void);
@@ -14,7 +14,7 @@ extern int g1 __attribute((alias("g0")));
// Make sure that aliases cause referenced values to be emitted.
// PR3200
-// RUN: grep 'define internal i32 @foo1()' %t &&
+// RUN: grep 'define internal i32 @foo1()' %t
static inline int foo1() { return 0; }
int foo() __attribute__((alias("foo1")));
diff --git a/test/CodeGen/alignof.c b/test/CodeGen/alignof.c
index d39f4e418eb1..71c275018ed5 100644
--- a/test/CodeGen/alignof.c
+++ b/test/CodeGen/alignof.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown -O1 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-unknown-unknown -O1 -emit-llvm -o %t %s
// RUN: grep 'ret i32 4' %t
enum e0 { E0 };
diff --git a/test/CodeGen/always_inline.c b/test/CodeGen/always_inline.c
index c12b45404d2d..d995ea11be09 100644
--- a/test/CodeGen/always_inline.c
+++ b/test/CodeGen/always_inline.c
@@ -1,7 +1,7 @@
-// RUN: clang -emit-llvm -S -o %t %s &&
-// RUN: not grep '@f0' %t &&
-// RUN: not grep 'call ' %t &&
-// RUN: clang -mllvm -disable-llvm-optzns -emit-llvm -S -o %t %s &&
+// RUN: clang -emit-llvm -S -o %t %s
+// RUN: not grep '@f0' %t
+// RUN: not grep 'call ' %t
+// RUN: clang -mllvm -disable-llvm-optzns -emit-llvm -S -o %t %s
// RUN: grep '@f0' %t | count 2
//static int f0() {
diff --git a/test/CodeGen/arm-arguments.c b/test/CodeGen/arm-arguments.c
index c43ede2ca05e..3b2c433a89ff 100644
--- a/test/CodeGen/arm-arguments.c
+++ b/test/CodeGen/arm-arguments.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple armv7-apple-darwin9 -target-abi=apcs-gnu -emit-llvm -w -o - %s | FileCheck -check-prefix=APCS-GNU %s &&
+// RUN: clang-cc -triple armv7-apple-darwin9 -target-abi=apcs-gnu -emit-llvm -w -o - %s | FileCheck -check-prefix=APCS-GNU %s
// RUN: clang-cc -triple armv7-apple-darwin9 -target-abi=aapcs -emit-llvm -w -o - %s | FileCheck -check-prefix=AAPCS %s
// APCS-GNU: define arm_apcscc signext i8 @f0()
diff --git a/test/CodeGen/asm-2.c b/test/CodeGen/asm-2.c
index f5b378eb1017..72b23b150592 100644
--- a/test/CodeGen/asm-2.c
+++ b/test/CodeGen/asm-2.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm %s -o %t -triple i386-pc-linux-gnu -O2 &&
+// RUN: clang-cc -emit-llvm %s -o %t -triple i386-pc-linux-gnu -O2
// RUN: not grep "load" %t
// <rdar://problem/6841383>
diff --git a/test/CodeGen/asm-inout.c b/test/CodeGen/asm-inout.c
index bd287ad0ee69..8ddd2acaf87c 100644
--- a/test/CodeGen/asm-inout.c
+++ b/test/CodeGen/asm-inout.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t
// RUN: grep "load i8\*\*\* %p.addr" %t | count 1
// XFAIL: *
diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c
index 52afc9152748..41951b8ac21f 100644
--- a/test/CodeGen/asm.c
+++ b/test/CodeGen/asm.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t
void t1(int len) {
__asm__ volatile("" : "=&r"(len), "+&r"(len));
}
@@ -28,12 +28,12 @@ void t6(void) {
__asm__ volatile("" : : "i" (t6));
}
-// RUN: grep "T7 NAMED: \$1" %t &&
+// RUN: grep "T7 NAMED: \$1" %t
void t7(int a) {
__asm__ volatile("T7 NAMED: %[input]" : "+r"(a): [input] "i" (4));
}
-// RUN: grep "T8 NAMED MODIFIER: \${0:c}" %t &&
+// RUN: grep "T8 NAMED MODIFIER: \${0:c}" %t
void t8() {
__asm__ volatile("T8 NAMED MODIFIER: %c[input]" :: [input] "i" (4));
}
diff --git a/test/CodeGen/atomic.c b/test/CodeGen/atomic.c
index 66dc702bfee9..355f7b83231e 100644
--- a/test/CodeGen/atomic.c
+++ b/test/CodeGen/atomic.c
@@ -1,14 +1,14 @@
-// RUN: clang-cc %s -emit-llvm -o - -triple=i686-apple-darwin9 > %t1 &&
-// RUN: grep @llvm.atomic.load.add.i32 %t1 | count 3 &&
-// RUN: grep @llvm.atomic.load.sub.i8 %t1 | count 2 &&
-// RUN: grep @llvm.atomic.load.min.i32 %t1 &&
-// RUN: grep @llvm.atomic.load.max.i32 %t1 &&
-// RUN: grep @llvm.atomic.load.umin.i32 %t1 &&
-// RUN: grep @llvm.atomic.load.umax.i32 %t1 &&
-// RUN: grep @llvm.atomic.swap.i32 %t1 &&
-// RUN: grep @llvm.atomic.cmp.swap.i32 %t1 | count 4 &&
-// RUN: grep @llvm.atomic.load.and.i32 %t1 | count 2 &&
-// RUN: grep @llvm.atomic.load.or.i8 %t1 &&
+// RUN: clang-cc %s -emit-llvm -o - -triple=i686-apple-darwin9 > %t1
+// RUN: grep @llvm.atomic.load.add.i32 %t1 | count 3
+// RUN: grep @llvm.atomic.load.sub.i8 %t1 | count 2
+// RUN: grep @llvm.atomic.load.min.i32 %t1
+// RUN: grep @llvm.atomic.load.max.i32 %t1
+// RUN: grep @llvm.atomic.load.umin.i32 %t1
+// RUN: grep @llvm.atomic.load.umax.i32 %t1
+// RUN: grep @llvm.atomic.swap.i32 %t1
+// RUN: grep @llvm.atomic.cmp.swap.i32 %t1 | count 4
+// RUN: grep @llvm.atomic.load.and.i32 %t1 | count 2
+// RUN: grep @llvm.atomic.load.or.i8 %t1
// RUN: grep @llvm.atomic.load.xor.i8 %t1
diff --git a/test/CodeGen/attr-nodebug.c b/test/CodeGen/attr-nodebug.c
index b96ad26d6d04..e0c813399fb9 100644
--- a/test/CodeGen/attr-nodebug.c
+++ b/test/CodeGen/attr-nodebug.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -g -emit-llvm -o %t %s &&
+// RUN: clang-cc -g -emit-llvm -o %t %s
// RUN: not grep 'call void @llvm.dbg.func.start' %t
void t1() __attribute__((nodebug));
diff --git a/test/CodeGen/attr-noinline.c b/test/CodeGen/attr-noinline.c
index 199c2918d425..719d6eb88fb3 100644
--- a/test/CodeGen/attr-noinline.c
+++ b/test/CodeGen/attr-noinline.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -g -emit-llvm -o %t %s &&
+// RUN: clang-cc -g -emit-llvm -o %t %s
// RUN: grep 'noinline' %t
void t1() __attribute__((noinline));
diff --git a/test/CodeGen/attr-used.c b/test/CodeGen/attr-used.c
index 8521ffd2e4bb..5537ec2f4cef 100644
--- a/test/CodeGen/attr-used.c
+++ b/test/CodeGen/attr-used.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
-// RUN: grep '@llvm.used = .*@g0' %t &&
-// RUN: grep '@llvm.used = .*@f0' %t &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: grep '@llvm.used = .*@g0' %t
+// RUN: grep '@llvm.used = .*@f0' %t
// RUN: grep '@llvm.used = .*@f1.l0' %t
diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c
index d539e033a7e9..29672c2ecb3d 100644
--- a/test/CodeGen/attributes.c
+++ b/test/CodeGen/attributes.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -triple i386-linux-gnu -o %t %s &&
+// RUN: clang-cc -emit-llvm -triple i386-linux-gnu -o %t %s
// RUN: FileCheck --input-file=%t %s
// CHECK: @t5 = weak global i32 2
@@ -69,8 +69,7 @@ int t19(void) {
}
// CHECK:define void @t20() nounwind {
-// CHECK-NEXT:entry:
-// CHECK-NEXT: call void @abort()
+// CHECK: call void @abort()
// CHECK-NEXT: unreachable
void t20(void) {
__builtin_abort();
diff --git a/test/CodeGen/bitfield-assign.c b/test/CodeGen/bitfield-assign.c
index 05d4dda353c7..575a9fb766cf 100644
--- a/test/CodeGen/bitfield-assign.c
+++ b/test/CodeGen/bitfield-assign.c
@@ -4,13 +4,13 @@
/* Check that we get one load for each simple assign and two for the
compound assign (load the old value before the add then load again
to store back). Also check that our g0 pattern is good. */
-// RUN: clang-cc -triple i386-unknown-unknown -O0 -emit-llvm -o %t %s &&
-// RUN: grep 'load ' %t | count 5 &&
-// RUN: grep "@g0" %t | count 4 &&
+// RUN: clang-cc -triple i386-unknown-unknown -O0 -emit-llvm -o %t %s
+// RUN: grep 'load ' %t | count 5
+// RUN: grep "@g0" %t | count 4
// Check that we got the right value.
-// RUN: clang-cc -triple i386-unknown-unknown -O3 -emit-llvm -o %t %s &&
-// RUN: grep 'load ' %t | count 0 &&
+// RUN: clang-cc -triple i386-unknown-unknown -O3 -emit-llvm -o %t %s
+// RUN: grep 'load ' %t | count 0
// RUN: grep "@g0" %t | count 0
struct s0 {
diff --git a/test/CodeGen/bitfield-promote.c b/test/CodeGen/bitfield-promote.c
index 5894e51626da..1290a1ecd33b 100644
--- a/test/CodeGen/bitfield-promote.c
+++ b/test/CodeGen/bitfield-promote.c
@@ -1,7 +1,6 @@
-// RUN: clang -O3 -emit-llvm -S -o %t %s &&
-// RUN: grep 'ret i64 4294967292' %t | count 2 &&
-// RUN: grep 'ret i64 -4' %t | count 1 &&
-// RUN: true
+// RUN: clang -O3 -emit-llvm -S -o %t %s
+// RUN: grep 'ret i64 4294967292' %t | count 2
+// RUN: grep 'ret i64 -4' %t | count 1
long long f0(void) {
struct { unsigned f0 : 32; } x = { 18 };
diff --git a/test/CodeGen/bitfield.c b/test/CodeGen/bitfield.c
index 02f2de79f6bc..9cd79d3d5870 100644
--- a/test/CodeGen/bitfield.c
+++ b/test/CodeGen/bitfield.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t -O3 &&
-// RUN: grep "ret i32" %t | count 4 &&
+// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t -O3
+// RUN: grep "ret i32" %t | count 4
// RUN: grep "ret i32 1" %t | count 4
static int f0(int n) {
diff --git a/test/CodeGen/blocks-1.c b/test/CodeGen/blocks-1.c
index 10498cb00495..ae5a74aab6f0 100644
--- a/test/CodeGen/blocks-1.c
+++ b/test/CodeGen/blocks-1.c
@@ -1,13 +1,13 @@
-// RUN: clang-cc %s -emit-llvm -o %t -fblocks &&
-// RUN: grep "_Block_object_dispose" %t | count 17 &&
-// RUN: grep "__copy_helper_block_" %t | count 16 &&
-// RUN: grep "__destroy_helper_block_" %t | count 16 &&
-// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 &&
-// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 &&
-// RUN: grep "i32 135)" %t | count 2 &&
+// RUN: clang-cc %s -emit-llvm -o %t -fblocks
+// RUN: grep "_Block_object_dispose" %t | count 17
+// RUN: grep "__copy_helper_block_" %t | count 16
+// RUN: grep "__destroy_helper_block_" %t | count 16
+// RUN: grep "__Block_byref_id_object_copy_" %t | count 2
+// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2
+// RUN: grep "i32 135)" %t | count 2
// RUN: grep "_Block_object_assign" %t | count 10
-#include <stdio.h>
+int printf(const char *, ...);
void test1() {
__block int a;
diff --git a/test/CodeGen/blocks-2.c b/test/CodeGen/blocks-2.c
index acbaafd95605..c22e882f1b79 100644
--- a/test/CodeGen/blocks-2.c
+++ b/test/CodeGen/blocks-2.c
@@ -1,5 +1,9 @@
-// RUN: clang-cc -g %s -emit-llvm -o %t -fblocks &&
+// RUN: clang-cc -g %s -emit-llvm -o %t -fblocks
// RUN: grep "func.start" %t | count 4
+// RUN: clang-cc -g %s -triple i386-unknown-unknown -emit-llvm -o %t -fblocks -fblock-introspection
+// RUN: grep "v8@?0i4" %t | count 1
+// RUN: clang-cc -g %s -triple i386-unknown-unknown -emit-llvm -o %t -fblocks
+// RUN: grep "v8@?0i4" %t | count 0
// 1 declaration, 1 bar, 1 test_block_dbg and 1 for the block.
// XFAIL: *
diff --git a/test/CodeGen/blocks-aligned-byref-variable.c b/test/CodeGen/blocks-aligned-byref-variable.c
index 1ae306254157..61522fd2da77 100644
--- a/test/CodeGen/blocks-aligned-byref-variable.c
+++ b/test/CodeGen/blocks-aligned-byref-variable.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -o - -triple x86_64-apple-darwin10 &&
+// RUN: clang-cc -emit-llvm -o - -triple x86_64-apple-darwin10
// RUN: clang-cc -emit-llvm -o - -triple i386-apple-darwin10
typedef int __attribute__((aligned(32))) ai;
diff --git a/test/CodeGen/blocks-seq.c b/test/CodeGen/blocks-seq.c
index 3ff241e3f6e3..4006b715f464 100644
--- a/test/CodeGen/blocks-seq.c
+++ b/test/CodeGen/blocks-seq.c
@@ -1,12 +1,12 @@
// FIXME: We forcibly strip the names so that the test doesn't vary between
// builds with and without asserts. We need a better solution for this.
-// RUN: clang-cc -fblocks -triple x86_64-apple-darwin10 -emit-llvm-bc -o - %s | opt -strip | llvm-dis > %t &&
-// RUN: grep '%6 = call i32 (...)\* @rhs()' %t | count 1 &&
-// RUN: grep '%7 = getelementptr inbounds %0\* %1, i32 0, i32 1' %t | count 1 &&
-// RUN: grep '%8 = load %0\*\* %7' %t | count 1 &&
-// RUN: grep '%10 = call i32 (...)\* @rhs()' %t | count 1 &&
-// RUN: grep '%11 = getelementptr inbounds %0\* %1, i32 0, i32 1' %t | count 1 &&
+// RUN: clang-cc -fblocks -triple x86_64-apple-darwin10 -emit-llvm-bc -o - %s | opt -strip | llvm-dis > %t
+// RUN: grep '%6 = call i32 (...)\* @rhs()' %t | count 1
+// RUN: grep '%7 = getelementptr inbounds %0\* %1, i32 0, i32 1' %t | count 1
+// RUN: grep '%8 = load %0\*\* %7' %t | count 1
+// RUN: grep '%10 = call i32 (...)\* @rhs()' %t | count 1
+// RUN: grep '%11 = getelementptr inbounds %0\* %1, i32 0, i32 1' %t | count 1
// RUN: grep '%12 = load %0\*\* %11' %t | count 1
int rhs();
diff --git a/test/CodeGen/blocks.c b/test/CodeGen/blocks.c
index 39c5b06b1727..eddf25c74a83 100644
--- a/test/CodeGen/blocks.c
+++ b/test/CodeGen/blocks.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t -fblocks &&
+// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t -fblocks
void (^f)(void) = ^{};
// rdar://6768379
@@ -12,7 +12,7 @@ struct s0 {
int a[64];
};
-// RUN: grep 'internal void @__f2_block_invoke_(.struct.s0\* noalias sret .*, .*, .* byval .*)' %t &&
+// RUN: grep 'internal void @__f2_block_invoke_(.struct.s0\* noalias sret .*, .*, .* byval .*)' %t
struct s0 f2(struct s0 a0) {
return ^(struct s0 a1){ return a1; }(a0);
}
@@ -27,4 +27,3 @@ void (^test1)(void) = ^(void) {
^ { i = 1; }();
};
-// RUN: true
diff --git a/test/CodeGen/builtin-count-zeros.c b/test/CodeGen/builtin-count-zeros.c
index 374acc43ae58..ff08bd108357 100644
--- a/test/CodeGen/builtin-count-zeros.c
+++ b/test/CodeGen/builtin-count-zeros.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm %s -o - | grep 'cttz' | count 2 &&
+// RUN: clang-cc -emit-llvm %s -o - | grep 'cttz' | count 2
// RUN: clang-cc -emit-llvm %s -o - | grep 'ctlz' | count 2
int a(int a) {return __builtin_ctz(a) + __builtin_clz(a);}
diff --git a/test/CodeGen/builtin-memfns.c b/test/CodeGen/builtin-memfns.c
index 9ae380c5455b..f1d092502dc2 100644
--- a/test/CodeGen/builtin-memfns.c
+++ b/test/CodeGen/builtin-memfns.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s &&
-// RUN: grep '@llvm.memset.i32' %t &&
-// RUN: grep '@llvm.memcpy.i32' %t &&
-// RUN: grep '@llvm.memmove.i32' %t &&
+// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: grep '@llvm.memset.i32' %t
+// RUN: grep '@llvm.memcpy.i32' %t
+// RUN: grep '@llvm.memmove.i32' %t
// RUN: grep __builtin %t | count 0
int main(int argc, char **argv) {
diff --git a/test/CodeGen/builtin-nanf.c b/test/CodeGen/builtin-nanf.c
index e048c7a1aa5a..8f7d2a1e443b 100644
--- a/test/CodeGen/builtin-nanf.c
+++ b/test/CodeGen/builtin-nanf.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s
// RUN: grep 'float 0x7FF8000000000000, float 0x7FF8000000000000, float 0x7FF8000020000000, float 0x7FF8000000000000, float 0x7FF80001E0000000, float 0x7FF8001E00000000, float 0x7FF801E000000000, float 0x7FF81E0000000000, float 0x7FF9E00000000000, float 0x7FFFFFFFE0000000' %t
float n[] = {
diff --git a/test/CodeGen/builtin-stackaddress.c b/test/CodeGen/builtin-stackaddress.c
index 5c6d540172a0..d8e58c4f6be7 100644
--- a/test/CodeGen/builtin-stackaddress.c
+++ b/test/CodeGen/builtin-stackaddress.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm < %s | grep "llvm.returnaddress" &&
+// RUN: clang-cc -emit-llvm < %s | grep "llvm.returnaddress"
// RUN: clang-cc -emit-llvm < %s | grep "llvm.frameaddress"
void* a(unsigned x) {
return __builtin_return_address(0);
diff --git a/test/CodeGen/builtins-ffs_parity_popcount.c b/test/CodeGen/builtins-ffs_parity_popcount.c
index e3fa4d2d8212..74e104b437c6 100644
--- a/test/CodeGen/builtins-ffs_parity_popcount.c
+++ b/test/CodeGen/builtins-ffs_parity_popcount.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -o - %s > %t &&
+// RUN: clang-cc -emit-llvm -o - %s > %t
// RUN: not grep "__builtin" %t
#include <stdio.h>
diff --git a/test/CodeGen/builtins-powi.c b/test/CodeGen/builtins-powi.c
index 57fa81a3ad12..945ec5dd13ea 100644
--- a/test/CodeGen/builtins-powi.c
+++ b/test/CodeGen/builtins-powi.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -o - %s > %t &&
+// RUN: clang-cc -emit-llvm -o - %s > %t
// RUN: not grep "__builtin" %t
#include <stdio.h>
diff --git a/test/CodeGen/builtins-x86.c b/test/CodeGen/builtins-x86.c
index f49e7b670dec..c82ecde1ff39 100644
--- a/test/CodeGen/builtins-x86.c
+++ b/test/CodeGen/builtins-x86.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -DUSE_64 -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
+// RUN: clang-cc -DUSE_64 -triple x86_64-unknown-unknown -emit-llvm -o %t %s
// RUN: clang-cc -DUSE_ALL -triple x86_64-unknown-unknown -fsyntax-only -o %t %s
#ifdef USE_ALL
diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c
index 359d5070ccc1..11bcc14249ac 100644
--- a/test/CodeGen/builtins.c
+++ b/test/CodeGen/builtins.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
+// RUN: clang-cc -emit-llvm -o %t %s
// RUN: not grep __builtin %t
-#include <stdio.h>
+int printf(const char *, ...);
void p(char *str, int x) {
printf("%s: %d\n", str, x);
diff --git a/test/CodeGen/c-strings.c b/test/CodeGen/c-strings.c
index ee85f60ed15a..2cf4036cb675 100644
--- a/test/CodeGen/c-strings.c
+++ b/test/CodeGen/c-strings.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
-// RUN: grep "hello" %t | count 3 &&
-// RUN: grep 'c"hello\\00"' %t | count 2 &&
-// RUN: grep 'c"hello\\00\\00\\00"' %t | count 1 &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: grep "hello" %t | count 3
+// RUN: grep 'c"hello\\00"' %t | count 2
+// RUN: grep 'c"hello\\00\\00\\00"' %t | count 1
// RUN: grep 'c"ola"' %t | count 1
/* Should be 3 hello string, two global (of different sizes), the rest
diff --git a/test/CodeGen/cleanup-stack.c b/test/CodeGen/cleanup-stack.c
index b0c5e88d55ec..3954d85de2b0 100644
--- a/test/CodeGen/cleanup-stack.c
+++ b/test/CodeGen/cleanup-stack.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown -O3 -emit-llvm %s -o %t &&
+// RUN: clang-cc -triple i386-unknown-unknown -O3 -emit-llvm %s -o %t
// RUN: grep "ret i32 9" %t
struct s0 {
diff --git a/test/CodeGen/compound-type.c b/test/CodeGen/compound-type.c
index 352f6cc3ce65..47eb3a6e57b6 100644
--- a/test/CodeGen/compound-type.c
+++ b/test/CodeGen/compound-type.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc < %s -emit-llvm -triple i686-pc-linux-gnu > %t &&
-// RUN: grep "div i32" %t &&
+// RUN: clang-cc < %s -emit-llvm -triple i686-pc-linux-gnu > %t
+// RUN: grep "div i32" %t
// RUN: grep "shl i32" %t
unsigned char a,b;
diff --git a/test/CodeGen/conditional.c b/test/CodeGen/conditional.c
index 8a30463cb7e4..f55d59071a2f 100644
--- a/test/CodeGen/conditional.c
+++ b/test/CodeGen/conditional.c
@@ -39,3 +39,11 @@ void _php_stream_free3() {
void _php_stream_free4() {
1 ? _efree(0) : free(0);
}
+
+// PR5526
+struct test9 { int a; };
+void* test9spare();
+void test9(struct test9 *p) {
+ p ? p : test9spare();
+}
+
diff --git a/test/CodeGen/const-init.c b/test/CodeGen/const-init.c
index e25da9c6eba0..06cdde9c9575 100644
--- a/test/CodeGen/const-init.c
+++ b/test/CodeGen/const-init.c
@@ -111,3 +111,15 @@ void *g20(void) {
// PR4108
struct g21 {int g21;};
const struct g21 g21 = (struct g21){1};
+
+// PR5474
+struct g22 {int x;} __attribute((packed));
+struct g23 {char a; short b; char c; struct g22 d;};
+struct g23 g24 = {1,2,3,4};
+
+// CHECK: @__func__.g25 = private constant [4 x i8] c"g25\00"
+// CHECK: @g25.g26 = internal global i8* getelementptr inbounds ([4 x i8]* @__func__.g25, i32 0, i32 0)
+int g25() {
+ static const char *g26 = __func__;
+ return *g26;
+}
diff --git a/test/CodeGen/constant-comparison.c b/test/CodeGen/constant-comparison.c
index ea3e8962b333..3089ae48e6e7 100644
--- a/test/CodeGen/constant-comparison.c
+++ b/test/CodeGen/constant-comparison.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm %s -o - 2>&1 | not grep warning &&
+// RUN: clang-cc -emit-llvm %s -o - 2>&1 | not grep warning
// RUN: clang-cc -emit-llvm %s -o - | grep @b | count 1
int a, b;
diff --git a/test/CodeGen/constructor-attribute.c b/test/CodeGen/constructor-attribute.c
index 9a1fa76c622a..b715201dc53b 100644
--- a/test/CodeGen/constructor-attribute.c
+++ b/test/CodeGen/constructor-attribute.c
@@ -1,10 +1,10 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
-// RUN: grep -e "global_ctors.*@A" %t &&
-// RUN: grep -e "global_dtors.*@B" %t &&
-// RUN: grep -e "global_ctors.*@C" %t &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: grep -e "global_ctors.*@A" %t
+// RUN: grep -e "global_dtors.*@B" %t
+// RUN: grep -e "global_ctors.*@C" %t
// RUN: grep -e "global_dtors.*@D" %t
-#include <stdio.h>
+int printf(const char *, ...);
void A() __attribute__((constructor));
void B() __attribute__((destructor));
diff --git a/test/CodeGen/darwin-string-literals.c b/test/CodeGen/darwin-string-literals.c
index 04e43a234d19..427e9c2e1b20 100644
--- a/test/CodeGen/darwin-string-literals.c
+++ b/test/CodeGen/darwin-string-literals.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck -check-prefix LSB %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck -check-prefix LSB %s
// CHECK-LSB: @.str = private constant [8 x i8] c"string0\00"
// CHECK-LSB: @.str1 = private constant [8 x i8] c"string1\00"
diff --git a/test/CodeGen/debug-info.c b/test/CodeGen/debug-info.c
index 85ad988bc216..856b91964ebc 100644
--- a/test/CodeGen/debug-info.c
+++ b/test/CodeGen/debug-info.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -o %t --emit-llvm -g %s &&
+// RUN: clang-cc -o %t --emit-llvm -g %s
// RUN: FileCheck --input-file=%t %s
// PR3023
diff --git a/test/CodeGen/designated-initializers.c b/test/CodeGen/designated-initializers.c
index f20bc782b6ac..cc88cef0dcdf 100644
--- a/test/CodeGen/designated-initializers.c
+++ b/test/CodeGen/designated-initializers.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t &&
-// RUN: grep "{ i8\* null, i32 1024 }" %t &&
+// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t
+// RUN: grep "{ i8\* null, i32 1024 }" %t
// RUN: grep "i32 0, i32 22" %t
struct foo {
diff --git a/test/CodeGen/dllimport-dllexport.c b/test/CodeGen/dllimport-dllexport.c
index fe49ae7a32af..6e259058b7a1 100644
--- a/test/CodeGen/dllimport-dllexport.c
+++ b/test/CodeGen/dllimport-dllexport.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -emit-llvm < %s -o %t &&
-// RUN: grep 'dllexport' %t | count 1 &&
+// RUN: clang-cc -emit-llvm < %s -o %t
+// RUN: grep 'dllexport' %t | count 1
// RUN: not grep 'dllimport' %t
void __attribute__((dllimport)) foo1();
diff --git a/test/CodeGen/emit-all-decls.c b/test/CodeGen/emit-all-decls.c
index 775cb6f118a8..3e7927d8ef79 100644
--- a/test/CodeGen/emit-all-decls.c
+++ b/test/CodeGen/emit-all-decls.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
-// RUN: not grep "@foo" %t &&
-// RUN: clang-cc -femit-all-decls -emit-llvm -o %t %s &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: not grep "@foo" %t
+// RUN: clang-cc -femit-all-decls -emit-llvm -o %t %s
// RUN: grep "@foo" %t
static void foo() {
diff --git a/test/CodeGen/ext-vector-shuffle.c b/test/CodeGen/ext-vector-shuffle.c
index 765551596401..88f8c242e880 100644
--- a/test/CodeGen/ext-vector-shuffle.c
+++ b/test/CodeGen/ext-vector-shuffle.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc %s -x cl -emit-llvm -o - | not grep 'extractelement' &&
-// RUN: clang-cc %s -x cl -emit-llvm -o - | not grep 'insertelement' &&
+// RUN: clang-cc %s -x cl -emit-llvm -o - | not grep 'extractelement'
+// RUN: clang-cc %s -x cl -emit-llvm -o - | not grep 'insertelement'
// RUN: clang-cc %s -x cl -emit-llvm -o - | grep 'shufflevector'
typedef __attribute__(( ext_vector_type(2) )) float float2;
diff --git a/test/CodeGen/flexible-array-init.c b/test/CodeGen/flexible-array-init.c
index fb98a8ec07a6..2f0df9057a9a 100644
--- a/test/CodeGen/flexible-array-init.c
+++ b/test/CodeGen/flexible-array-init.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 7 | count 1 &&
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 11 | count 1 &&
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 13 | count 1 &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 7 | count 1
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 11 | count 1
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 13 | count 1
// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 15 | count 1
struct { int x; int y[]; } a = { 1, 7, 11 };
diff --git a/test/CodeGen/functions.c b/test/CodeGen/functions.c
index dba29316e1a3..1c53db411961 100644
--- a/test/CodeGen/functions.c
+++ b/test/CodeGen/functions.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -emit-llvm -o %t &&
+// RUN: clang-cc %s -emit-llvm -o %t
int g();
@@ -19,15 +19,15 @@ void test3(T f) {
int a(int);
int a() {return 1;}
-// RUN: grep 'define void @f0()' %t &&
+// RUN: grep 'define void @f0()' %t
void f0() {}
void f1();
-// RUN: grep 'call void @f1()' %t &&
+// RUN: grep 'call void @f1()' %t
void f2(void) {
f1(1, 2, 3);
}
-// RUN: grep 'define void @f1()' %t &&
+// RUN: grep 'define void @f1()' %t
void f1() {}
// RUN: grep 'define .* @f3' %t | not grep -F '...'
diff --git a/test/CodeGen/global-decls.c b/test/CodeGen/global-decls.c
index decb6a981c7f..c7a70fa237ac 100644
--- a/test/CodeGen/global-decls.c
+++ b/test/CodeGen/global-decls.c
@@ -1,16 +1,16 @@
-// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s
-// RUN: grep '@g0_ext = extern_weak global i32' %t &&
+// RUN: grep '@g0_ext = extern_weak global i32' %t
extern int g0_ext __attribute__((weak));
-// RUN: grep 'declare extern_weak i32 @g1_ext()' %t &&
+// RUN: grep 'declare extern_weak i32 @g1_ext()' %t
extern int __attribute__((weak)) g1_ext (void);
-// RUN: grep '@g0_common = weak global i32' %t &&
+// RUN: grep '@g0_common = weak global i32' %t
int g0_common __attribute__((weak));
-// RUN: grep '@g0_def = weak global i32' %t &&
+// RUN: grep '@g0_def = weak global i32' %t
int g0_def __attribute__((weak)) = 52;
-// RUN: grep 'define weak i32 @g1_def()' %t &&
+// RUN: grep 'define weak i32 @g1_def()' %t
int __attribute__((weak)) g1_def (void) { return 0; }
// Force _ext references
@@ -19,4 +19,3 @@ void f0() {
int b = g1_ext();
}
-// RUN: true
diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c
index 2e239cf5438c..b0537ae5b077 100644
--- a/test/CodeGen/init.c
+++ b/test/CodeGen/init.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t
void f1() {
// Scalars in braces.
@@ -22,7 +22,7 @@ void f3() {
}
// Constants
-// RUN: grep '@g3 = constant i32 10' %t &&
+// RUN: grep '@g3 = constant i32 10' %t
// RUN: grep '@f4.g4 = internal constant i32 12' %t
const int g3 = 10;
int f4() {
diff --git a/test/CodeGen/inline.c b/test/CodeGen/inline.c
index bf17fd7c22ba..76d90eda2100 100644
--- a/test/CodeGen/inline.c
+++ b/test/CodeGen/inline.c
@@ -1,40 +1,40 @@
-// RUN: echo "GNU89 tests:" &&
-// RUN: clang %s -emit-llvm -S -o %t -std=gnu89 &&
-// RUN: grep "define available_externally i32 @ei()" %t &&
-// RUN: grep "define i32 @foo()" %t &&
-// RUN: grep "define i32 @bar()" %t &&
-// RUN: grep "define void @unreferenced1()" %t &&
-// RUN: not grep unreferenced2 %t &&
-// RUN: grep "define void @gnu_inline()" %t &&
-// RUN: grep "define available_externally void @gnu_ei_inline()" %t &&
-// RUN: grep "define i32 @test1" %t &&
-// RUN: grep "define i32 @test2" %t &&
-// RUN: grep "define void @test3()" %t &&
-// RUN: grep "define available_externally i32 @test4" %t &&
-// RUN: grep "define available_externally i32 @test5" %t &&
-
-// RUN: echo "\nC99 tests:" &&
-// RUN: clang %s -emit-llvm -S -o %t -std=c99 &&
-// RUN: grep "define i32 @ei()" %t &&
-// RUN: grep "define available_externally i32 @foo()" %t &&
-// RUN: grep "define i32 @bar()" %t &&
-// RUN: not grep unreferenced1 %t &&
-// RUN: grep "define void @unreferenced2()" %t &&
-// RUN: grep "define void @gnu_inline()" %t &&
-// RUN: grep "define available_externally void @gnu_ei_inline()" %t &&
-// RUN: grep "define i32 @test1" %t &&
-// RUN: grep "define i32 @test2" %t &&
-// RUN: grep "define void @test3" %t &&
-// RUN: grep "define available_externally i32 @test4" %t &&
-// RUN: grep "define available_externally i32 @test5" %t &&
-
-// RUN: echo "\nC++ tests:" &&
-// RUN: clang %s -emit-llvm -S -o %t -std=c++98 &&
-// RUN: grep "define linkonce_odr i32 @_Z2eiv()" %t &&
-// RUN: grep "define linkonce_odr i32 @_Z3foov()" %t &&
-// RUN: grep "define i32 @_Z3barv()" %t &&
-// RUN: not grep unreferenced %t &&
-// RUN: grep "define void @_Z10gnu_inlinev()" %t &&
+// RUN: echo "GNU89 tests:"
+// RUN: clang %s -emit-llvm -S -o %t -std=gnu89
+// RUN: grep "define available_externally i32 @ei()" %t
+// RUN: grep "define i32 @foo()" %t
+// RUN: grep "define i32 @bar()" %t
+// RUN: grep "define void @unreferenced1()" %t
+// RUN: not grep unreferenced2 %t
+// RUN: grep "define void @gnu_inline()" %t
+// RUN: grep "define available_externally void @gnu_ei_inline()" %t
+// RUN: grep "define i32 @test1" %t
+// RUN: grep "define i32 @test2" %t
+// RUN: grep "define void @test3()" %t
+// RUN: grep "define available_externally i32 @test4" %t
+// RUN: grep "define available_externally i32 @test5" %t
+
+// RUN: echo "\nC99 tests:"
+// RUN: clang %s -emit-llvm -S -o %t -std=c99
+// RUN: grep "define i32 @ei()" %t
+// RUN: grep "define available_externally i32 @foo()" %t
+// RUN: grep "define i32 @bar()" %t
+// RUN: not grep unreferenced1 %t
+// RUN: grep "define void @unreferenced2()" %t
+// RUN: grep "define void @gnu_inline()" %t
+// RUN: grep "define available_externally void @gnu_ei_inline()" %t
+// RUN: grep "define i32 @test1" %t
+// RUN: grep "define i32 @test2" %t
+// RUN: grep "define void @test3" %t
+// RUN: grep "define available_externally i32 @test4" %t
+// RUN: grep "define available_externally i32 @test5" %t
+
+// RUN: echo "\nC++ tests:"
+// RUN: clang %s -emit-llvm -S -o %t -std=c++98
+// RUN: grep "define linkonce_odr i32 @_Z2eiv()" %t
+// RUN: grep "define linkonce_odr i32 @_Z3foov()" %t
+// RUN: grep "define i32 @_Z3barv()" %t
+// RUN: not grep unreferenced %t
+// RUN: grep "define void @_Z10gnu_inlinev()" %t
// RUN: grep "define available_externally void @_Z13gnu_ei_inlinev()" %t
extern __inline int ei() { return 123; }
diff --git a/test/CodeGen/inline2.c b/test/CodeGen/inline2.c
index 6f165f50f8b7..304d6168578c 100644
--- a/test/CodeGen/inline2.c
+++ b/test/CodeGen/inline2.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -std=gnu89 -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck -check-prefix GNU89 %s &&
+// RUN: clang-cc -std=gnu89 -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck -check-prefix GNU89 %s
// RUN: clang-cc -std=c99 -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck -check-prefix C99 %s
// CHECK-GNU89: define i32 @f0()
diff --git a/test/CodeGen/libcalls.c b/test/CodeGen/libcalls.c
index ea9e0c3dd91b..cbbde8a9f3fd 100644
--- a/test/CodeGen/libcalls.c
+++ b/test/CodeGen/libcalls.c
@@ -1,8 +1,8 @@
-// RUN: clang-cc -fmath-errno=1 -emit-llvm -o %t %s -triple i386-unknown-unknown &&
-// RUN: grep "declare " %t | count 6 &&
-// RUN: grep "declare " %t | grep "@llvm." | count 1 &&
-// RUN: clang-cc -fmath-errno=0 -emit-llvm -o %t %s -triple i386-unknown-unknown &&
-// RUN: grep "declare " %t | count 6 &&
+// RUN: clang-cc -fmath-errno=1 -emit-llvm -o %t %s -triple i386-unknown-unknown
+// RUN: grep "declare " %t | count 6
+// RUN: grep "declare " %t | grep "@llvm." | count 1
+// RUN: clang-cc -fmath-errno=0 -emit-llvm -o %t %s -triple i386-unknown-unknown
+// RUN: grep "declare " %t | count 6
// RUN: grep "declare " %t | grep -v "@llvm." | count 0
// IRgen only pays attention to const; it should always call llvm for
diff --git a/test/CodeGen/lineno-dbginfo.c b/test/CodeGen/lineno-dbginfo.c
index 12c32ce9dd4b..b78dd21d72b3 100644
--- a/test/CodeGen/lineno-dbginfo.c
+++ b/test/CodeGen/lineno-dbginfo.c
@@ -1,6 +1,6 @@
-// RUN: echo "#include <stdio.h>" > %t.h &&
-// RUN: clang -S -save-temps -g -include %t.h %s -emit-llvm -o %t.ll &&
-// RUN: grep "i32 5" %t.ll &&
+// RUN: echo "#include <stdio.h>" > %t.h
+// RUN: clang -S -save-temps -g -include %t.h %s -emit-llvm -o %t.ll
+// RUN: grep "i32 5" %t.ll
// RUN: rm -f lineno-dbginfo.i
// outer is at line number 5.
int outer = 42;
diff --git a/test/CodeGen/mandel.c b/test/CodeGen/mandel.c
index 27993f0559e9..9d7956c56d1b 100644
--- a/test/CodeGen/mandel.c
+++ b/test/CodeGen/mandel.c
@@ -25,7 +25,7 @@ int main() { return 0; }
#define I 1.0iF
-#include <stdio.h>
+int putchar(char c);
volatile double __complex__ accum;
diff --git a/test/CodeGen/no-common.c b/test/CodeGen/no-common.c
index 190873c745fe..64e37d78f964 100644
--- a/test/CodeGen/no-common.c
+++ b/test/CodeGen/no-common.c
@@ -1,6 +1,6 @@
-// RUN: clang -emit-llvm -S -o %t %s &&
-// RUN: grep '@x = common global' %t &&
-// RUN: clang -fno-common -emit-llvm -S -o %t %s &&
+// RUN: clang -emit-llvm -S -o %t %s
+// RUN: grep '@x = common global' %t
+// RUN: clang -fno-common -emit-llvm -S -o %t %s
// RUN: grep '@x = global' %t
int x;
diff --git a/test/CodeGen/object-size.c b/test/CodeGen/object-size.c
index 61d85419fc69..038d8f98e5d5 100644
--- a/test/CodeGen/object-size.c
+++ b/test/CodeGen/object-size.c
@@ -15,39 +15,39 @@ int gi, gj;
void test1() {
// CHECK: movabsq $59, %rdx
- // CHECK-NEXT: movq %rax, %rdi
- // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: movq
+ // CHECK-NEXT: movq
// CHECK-NEXT: call ___strcpy_chk
strcpy(&gbuf[4], "Hi there");
}
void test2() {
// CHECK: movabsq $63, %rdx
- // CHECK-NEXT: movq %rax, %rdi
- // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: movq
+ // CHECK-NEXT: movq
// CHECK-NEXT: call ___strcpy_chk
strcpy(gbuf, "Hi there");
}
void test3() {
// CHECK: movabsq $0, %rdx
- // CHECK-NEXT: movq %rax, %rdi
- // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: movq
+ // CHECK-NEXT: movq
// CHECK-NEXT: call ___strcpy_chk
strcpy(&gbuf[100], "Hi there");
}
void test4() {
// CHECK: movabsq $0, %rdx
- // CHECK-NEXT: movq %rax, %rdi
- // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: movq
+ // CHECK-NEXT: movq
// CHECK-NEXT: call ___strcpy_chk
strcpy((char*)(void*)&gbuf[-1], "Hi there");
}
void test5() {
- // CHECK: movb $0, %al
- // CHECK-NEXT: testb %al, %al
+ // CHECK: movq $-1, %rax
+ // CHECK-NEXT: cmpq $-1, %rax
// CHECK: call ___inline_strcpy_chk
strcpy(gp, "Hi there");
}
@@ -56,8 +56,8 @@ void test6() {
char buf[57];
// CHECK: movabsq $53, %rdx
- // CHECK-NEXT: movq %rax, %rdi
- // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: movq
+ // CHECK-NEXT: movq
// CHECK-NEXT: call ___strcpy_chk
strcpy(&buf[4], "Hi there");
}
diff --git a/test/CodeGen/packed-union.c b/test/CodeGen/packed-union.c
index d11d3a490234..41dc94c7a410 100644
--- a/test/CodeGen/packed-union.c
+++ b/test/CodeGen/packed-union.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm %s -o %t &&
+// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm %s -o %t
-// RUN: grep "struct._attrs = type <{ i32, i8 }>" %t &&
+// RUN: grep "struct._attrs = type <{ i32, i8 }>" %t
typedef struct _attrs {
unsigned file_attributes;
unsigned char filename_length;
diff --git a/test/CodeGen/parameter-passing.c b/test/CodeGen/parameter-passing.c
index dce0ff80cdc4..966223a39f56 100644
--- a/test/CodeGen/parameter-passing.c
+++ b/test/CodeGen/parameter-passing.c
@@ -5,15 +5,14 @@
// We also check _Bool and empty structures, as these can have annoying
// corner cases.
-// RUN: clang-cc %s -triple i386-unknown-unknown -O3 -emit-llvm -o %t &&
-// RUN: not grep '@g0' %t &&
+// RUN: clang-cc %s -triple i386-unknown-unknown -O3 -emit-llvm -o %t
+// RUN: not grep '@g0' %t
-// RUN: clang-cc %s -triple x86_64-unknown-unknown -O3 -emit-llvm -o %t &&
-// RUN: not grep '@g0' %t &&
+// RUN: clang-cc %s -triple x86_64-unknown-unknown -O3 -emit-llvm -o %t
+// RUN: not grep '@g0' %t
-// RUN: clang-cc %s -triple powerpc-unknown-unknown -O3 -emit-llvm -o %t &&
-// RUN: not grep '@g0' %t &&
-// RUN: true
+// RUN: clang-cc %s -triple powerpc-unknown-unknown -O3 -emit-llvm -o %t
+// RUN: not grep '@g0' %t
typedef _Bool BoolTy;
typedef int ScalarTy;
diff --git a/test/CodeGen/pragma-pack-2.c b/test/CodeGen/pragma-pack-2.c
index 306f02dd8cfe..bfc5dc943c5e 100644
--- a/test/CodeGen/pragma-pack-2.c
+++ b/test/CodeGen/pragma-pack-2.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 %s -emit-llvm -o - | FileCheck -check-prefix X32 %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 %s -emit-llvm -o - | FileCheck -check-prefix X32 %s
// CHECK-X32: %struct.s0 = type { i64, i64, i32, [12 x i32] }
// CHECK-X32: %struct.s1 = type { [15 x i32], %struct.s0 }
diff --git a/test/CodeGen/pragma-pack-3.c b/test/CodeGen/pragma-pack-3.c
index b9166ae5d390..56a6be3874fa 100644
--- a/test/CodeGen/pragma-pack-3.c
+++ b/test/CodeGen/pragma-pack-3.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 %s -emit-llvm -o - | FileCheck -check-prefix X32 %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 %s -emit-llvm -o - | FileCheck -check-prefix X32 %s
// CHECK-X32: %struct.menu = type <{ i8*, i8, i8 }>
// CHECK-X32: %union.command = type <{ i8*, [2 x i8] }>
diff --git a/test/CodeGen/predefined-expr.c b/test/CodeGen/predefined-expr.c
index 9b645931a4a7..1a5dcb4fc6ff 100644
--- a/test/CodeGen/predefined-expr.c
+++ b/test/CodeGen/predefined-expr.c
@@ -9,7 +9,7 @@
// CHECK: @__func__.staticFunction = private constant [15 x i8] c"staticFunction\00"
// CHECK: @__PRETTY_FUNCTION__.staticFunction = private constant [22 x i8] c"void staticFunction()\00"
-#include <stdio.h>
+int printf(const char *, ...);
void plainFunction() {
printf("__func__ %s\n", __func__);
diff --git a/test/CodeGen/private-extern.c b/test/CodeGen/private-extern.c
index f3ffe5461d06..a9bb28bfad4e 100644
--- a/test/CodeGen/private-extern.c
+++ b/test/CodeGen/private-extern.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
-// RUN: grep '@g0 = external hidden constant i32' %t &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: grep '@g0 = external hidden constant i32' %t
// RUN: grep '@g1 = hidden constant i32 1' %t
__private_extern__ const int g0;
diff --git a/test/CodeGen/rdr-6098585-default-after-caserange.c b/test/CodeGen/rdr-6098585-default-after-caserange.c
index 3a11ad64299c..239383a4bdca 100644
--- a/test/CodeGen/rdr-6098585-default-after-caserange.c
+++ b/test/CodeGen/rdr-6098585-default-after-caserange.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t &&
-// RUN: grep "ret i32" %t | count 1 &&
+// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
+// RUN: grep "ret i32" %t | count 1
// RUN: grep "ret i32 10" %t | count 1
// Ensure that default after a case range is not ignored.
diff --git a/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c b/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c
index f1d15dcd4fd5..39a6bc662dcb 100644
--- a/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c
+++ b/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t &&
+// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
// RUN: grep "ret i32 10" %t
// Ensure that this doesn't compile to infinite loop in g() due to
diff --git a/test/CodeGen/rdr-6098585-empty-case-range.c b/test/CodeGen/rdr-6098585-empty-case-range.c
index ca5ff1b71225..f80b599ed5a0 100644
--- a/test/CodeGen/rdr-6098585-empty-case-range.c
+++ b/test/CodeGen/rdr-6098585-empty-case-range.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t &&
-// RUN: grep "ret i32" %t | count 2 &&
+// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
+// RUN: grep "ret i32" %t | count 2
// RUN: grep "ret i32 3" %t | count 2
// This generated incorrect code because of poor switch chaining.
diff --git a/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c b/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c
index b34744970610..6c51a3706716 100644
--- a/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c
+++ b/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t &&
+// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
// RUN: grep "ret i32 %" %t
// Make sure return is not constant (if empty range is skipped or miscompiled)
diff --git a/test/CodeGen/rdr-6098585-unsigned-caserange.c b/test/CodeGen/rdr-6098585-unsigned-caserange.c
index 80035982e1f4..3b4384bdd70f 100644
--- a/test/CodeGen/rdr-6098585-unsigned-caserange.c
+++ b/test/CodeGen/rdr-6098585-unsigned-caserange.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t &&
-// RUN: grep "ret i32" %t | count 1 &&
+// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
+// RUN: grep "ret i32" %t | count 1
// RUN: grep "ret i32 3" %t | count 1
int f2(unsigned x) {
diff --git a/test/CodeGen/stack-protector.c b/test/CodeGen/stack-protector.c
index 0b5924d81112..c29d1f7f33d9 100644
--- a/test/CodeGen/stack-protector.c
+++ b/test/CodeGen/stack-protector.c
@@ -1,16 +1,9 @@
-// RUN: clang-cc -triple i686-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: not grep 'ssp' %t &&
-// RUN: clang-cc -triple i686-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: not grep 'ssp' %t &&
-// RUN: clang-cc -triple i686-apple-darwin10 -emit-llvm -o %t %s &&
-// RUN: grep 'ssp' %t &&
-// RUN: clang -fstack-protector-all -emit-llvm -S -o %t %s &&
-// RUN: grep 'sspreq' %t &&
-// RUN: clang -fstack-protector -emit-llvm -S -o %t %s &&
-// RUN: grep 'ssp' %t &&
-// RUN: clang -fno-stack-protector -emit-llvm -S -o %t %s &&
-// RUN: not grep 'ssp' %t &&
-// RUN: true
+// RUN: clang-cc -emit-llvm -o - %s -stack-protector=0 | FileCheck -check-prefix=NOSSP %s
+// NOSSP: define void @test1(i8* %msg) nounwind {
+// RUN: clang-cc -emit-llvm -o - %s -stack-protector=1 | FileCheck -check-prefix=WITHSSP %s
+// WITHSSP: define void @test1(i8* %msg) nounwind ssp {
+// RUN: clang-cc -emit-llvm -o - %s -stack-protector=2 | FileCheck -check-prefix=SSPREQ %s
+// SSPREQ: define void @test1(i8* %msg) nounwind sspreq {
int printf(const char * _Format, ...);
diff --git a/test/CodeGen/staticinit.c b/test/CodeGen/staticinit.c
index c68366f2ea77..8b87ccd6b905 100644
--- a/test/CodeGen/staticinit.c
+++ b/test/CodeGen/staticinit.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s &&
-// RUN: grep "g.b = internal global i8. getelementptr" %t &&
+// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: grep "g.b = internal global i8. getelementptr" %t
struct AStruct {
int i;
diff --git a/test/CodeGen/stdcall-fastcall.c b/test/CodeGen/stdcall-fastcall.c
index 89ed8c9ef672..11b652178ca8 100644
--- a/test/CodeGen/stdcall-fastcall.c
+++ b/test/CodeGen/stdcall-fastcall.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm < %s | grep 'fastcallcc' | count 4 &&
+// RUN: clang-cc -emit-llvm < %s | grep 'fastcallcc' | count 4
// RUN: clang-cc -emit-llvm < %s | grep 'stdcallcc' | count 4
void __attribute__((fastcall)) f1(void);
diff --git a/test/CodeGen/string-init.c b/test/CodeGen/string-init.c
index 4a808512601e..0cb6afff611d 100644
--- a/test/CodeGen/string-init.c
+++ b/test/CodeGen/string-init.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -emit-llvm %s -o %t &&
-// RUN: grep 'private constant \[10 x i8\]' %t &&
-// RUN: not grep -F "[5 x i8]" %t &&
+// RUN: clang-cc -emit-llvm %s -o %t
+// RUN: grep 'private constant \[10 x i8\]' %t
+// RUN: not grep -F "[5 x i8]" %t
// RUN: not grep "store " %t
void test(void) {
diff --git a/test/CodeGen/struct-passing.c b/test/CodeGen/struct-passing.c
index 9a4f47651b74..772077a5964f 100644
--- a/test/CodeGen/struct-passing.c
+++ b/test/CodeGen/struct-passing.c
@@ -1,11 +1,10 @@
-// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s &&
-// RUN: grep 'declare i32 @f0() readnone$' %t &&
-// RUN: grep 'declare i32 @f1() readonly$' %t &&
-// RUN: grep 'declare void @f2(.* noalias sret)$' %t &&
-// RUN: grep 'declare void @f3(.* noalias sret)$' %t &&
-// RUN: grep 'declare void @f4(.* byval)$' %t &&
-// RUN: grep 'declare void @f5(.* byval)$' %t &&
-// RUN: true
+// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: grep 'declare i32 @f0() readnone$' %t
+// RUN: grep 'declare i32 @f1() readonly$' %t
+// RUN: grep 'declare void @f2(.* noalias sret)$' %t
+// RUN: grep 'declare void @f3(.* noalias sret)$' %t
+// RUN: grep 'declare void @f4(.* byval)$' %t
+// RUN: grep 'declare void @f5(.* byval)$' %t
// PR3835
typedef int T0;
diff --git a/test/CodeGen/struct-x86-darwin.c b/test/CodeGen/struct-x86-darwin.c
index c61005f1bebd..e7822f073d2a 100644
--- a/test/CodeGen/struct-x86-darwin.c
+++ b/test/CodeGen/struct-x86-darwin.c
@@ -1,12 +1,12 @@
-// RUN: clang-cc < %s -emit-llvm > %t1 -triple=i686-apple-darwin9 &&
-// RUN: grep "STest1 = type { i32, \[4 x i16\], double }" %t1 &&
-// RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1 &&
-// RUN: grep "STest3 = type { i8, i16, i32 }" %t1 &&
-// RUN: grep "STestB1 = type { i8, i8 }" %t1 &&
-// RUN: grep "STestB2 = type { i8, i8, i8 }" %t1 &&
-// RUN: grep "STestB3 = type { i8, i8 }" %t1 &&
-// RUN: grep "STestB4 = type { i8, i8, i8, i8 }" %t1 &&
-// RUN: grep "STestB5 = type { i8, i8, \[2 x i8\], i8, i8 }" %t1 &&
+// RUN: clang-cc < %s -emit-llvm > %t1 -triple=i686-apple-darwin9
+// RUN: grep "STest1 = type { i32, \[4 x i16\], double }" %t1
+// RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1
+// RUN: grep "STest3 = type { i8, i16, i32 }" %t1
+// RUN: grep "STestB1 = type { i8, i8 }" %t1
+// RUN: grep "STestB2 = type { i8, i8, i8 }" %t1
+// RUN: grep "STestB3 = type { i8, i8 }" %t1
+// RUN: grep "STestB4 = type { i8, i8, i8, i8 }" %t1
+// RUN: grep "STestB5 = type { i8, i8, \[2 x i8\], i8, i8 }" %t1
// RUN: grep "STestB6 = type { i8, i8, \[2 x i8\] }" %t1
// Test struct layout for x86-darwin target
diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c
index 9d73d5c6300d..26775f98117c 100644
--- a/test/CodeGen/target-data.c
+++ b/test/CodeGen/target-data.c
@@ -1,7 +1,6 @@
-// RUN: clang-cc -triple i686-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: grep 'target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"' %t &&
-// RUN: clang-cc -triple i686-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: grep 'target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"' %t &&
-// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: grep 'target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"' %t &&
-// RUN: true
+// RUN: clang-cc -triple i686-unknown-unknown -emit-llvm -o %t %s
+// RUN: grep 'target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"' %t
+// RUN: clang-cc -triple i686-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep 'target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"' %t
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s
+// RUN: grep 'target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"' %t
diff --git a/test/CodeGen/tentative-decls.c b/test/CodeGen/tentative-decls.c
index 3301c234c55a..b72c5850ac2c 100644
--- a/test/CodeGen/tentative-decls.c
+++ b/test/CodeGen/tentative-decls.c
@@ -1,16 +1,16 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
+// RUN: clang-cc -emit-llvm -o %t %s
-// RUN: grep '@r = common global \[1 x .*\] zeroinitializer' %t &&
+// RUN: grep '@r = common global \[1 x .*\] zeroinitializer' %t
int r[];
int (*a)[] = &r;
struct s0;
struct s0 x;
-// RUN: grep '@x = common global .struct.s0 zeroinitializer' %t &&
+// RUN: grep '@x = common global .struct.s0 zeroinitializer' %t
struct s0 y;
-// RUN: grep '@y = common global .struct.s0 zeroinitializer' %t &&
+// RUN: grep '@y = common global .struct.s0 zeroinitializer' %t
struct s0 *f0() {
return &y;
}
@@ -19,21 +19,20 @@ struct s0 {
int x;
};
-// RUN: grep '@b = common global \[1 x .*\] zeroinitializer' %t &&
+// RUN: grep '@b = common global \[1 x .*\] zeroinitializer' %t
int b[];
int *f1() {
return b;
}
// Check that the most recent tentative definition wins.
-// RUN: grep '@c = common global \[4 x .*\] zeroinitializer' %t &&
+// RUN: grep '@c = common global \[4 x .*\] zeroinitializer' %t
int c[];
int c[4];
// Check that we emit static tentative definitions
-// RUN: grep '@c5 = internal global \[1 x .*\] zeroinitializer' %t &&
+// RUN: grep '@c5 = internal global \[1 x .*\] zeroinitializer' %t
static int c5[];
static int func() { return c5[0]; }
int callfunc() { return func(); }
-// RUN: true
diff --git a/test/CodeGen/trapv.c b/test/CodeGen/trapv.c
index c96488b8e99b..6045ed908d0e 100644
--- a/test/CodeGen/trapv.c
+++ b/test/CodeGen/trapv.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -ftrapv %s -emit-llvm -o %t &&
+// RUN: clang-cc -ftrapv %s -emit-llvm -o %t
// RUN: grep "__overflow_handler" %t | count 2
unsigned int ui, uj, uk;
diff --git a/test/CodeGen/unreachable.c b/test/CodeGen/unreachable.c
index ea4f0478bbd4..3f39a27def97 100644
--- a/test/CodeGen/unreachable.c
+++ b/test/CodeGen/unreachable.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
+// RUN: clang-cc -emit-llvm -o %t %s
// RUN: grep '@unreachable' %t | count 0
extern void abort() __attribute__((noreturn));
diff --git a/test/CodeGen/unwind-attr.c b/test/CodeGen/unwind-attr.c
index 86036f94b981..1148ba10315e 100644
--- a/test/CodeGen/unwind-attr.c
+++ b/test/CodeGen/unwind-attr.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fexceptions -emit-llvm -o - %s | grep "@foo()" | not grep nounwind &&
+// RUN: clang-cc -fexceptions -emit-llvm -o - %s | grep "@foo()" | not grep nounwind
// RUN: clang-cc -emit-llvm -o - %s | grep "@foo()" | grep nounwind
int foo(void) {
diff --git a/test/CodeGen/visibility.c b/test/CodeGen/visibility.c
index 958eb618ee70..7c837ba823e9 100644
--- a/test/CodeGen/visibility.c
+++ b/test/CodeGen/visibility.c
@@ -1,28 +1,27 @@
-// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=default -emit-llvm -o %t %s &&
-// RUN: grep '@g_com = common global i32 0' %t &&
-// RUN: grep '@g_def = global i32 0' %t &&
-// RUN: grep '@g_ext = external global i32' %t &&
-// RUN: grep '@g_deferred = internal global' %t &&
-// RUN: grep 'declare void @f_ext()' %t &&
-// RUN: grep 'define internal void @f_deferred()' %t &&
-// RUN: grep 'define i32 @f_def()' %t &&
-// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=protected -emit-llvm -o %t %s &&
-// RUN: grep '@g_com = common protected global i32 0' %t &&
-// RUN: grep '@g_def = protected global i32 0' %t &&
-// RUN: grep '@g_ext = external global i32' %t &&
-// RUN: grep '@g_deferred = internal global' %t &&
-// RUN: grep 'declare void @f_ext()' %t &&
-// RUN: grep 'define internal void @f_deferred()' %t &&
-// RUN: grep 'define protected i32 @f_def()' %t &&
-// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=hidden -emit-llvm -o %t %s &&
-// RUN: grep '@g_com = common hidden global i32 0' %t &&
-// RUN: grep '@g_def = hidden global i32 0' %t &&
-// RUN: grep '@g_ext = external global i32' %t &&
-// RUN: grep '@g_deferred = internal global' %t &&
-// RUN: grep 'declare void @f_ext()' %t &&
-// RUN: grep 'define internal void @f_deferred()' %t &&
-// RUN: grep 'define hidden i32 @f_def()' %t &&
-// RUN: true
+// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=default -emit-llvm -o %t %s
+// RUN: grep '@g_com = common global i32 0' %t
+// RUN: grep '@g_def = global i32 0' %t
+// RUN: grep '@g_ext = external global i32' %t
+// RUN: grep '@g_deferred = internal global' %t
+// RUN: grep 'declare void @f_ext()' %t
+// RUN: grep 'define internal void @f_deferred()' %t
+// RUN: grep 'define i32 @f_def()' %t
+// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=protected -emit-llvm -o %t %s
+// RUN: grep '@g_com = common protected global i32 0' %t
+// RUN: grep '@g_def = protected global i32 0' %t
+// RUN: grep '@g_ext = external global i32' %t
+// RUN: grep '@g_deferred = internal global' %t
+// RUN: grep 'declare void @f_ext()' %t
+// RUN: grep 'define internal void @f_deferred()' %t
+// RUN: grep 'define protected i32 @f_def()' %t
+// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=hidden -emit-llvm -o %t %s
+// RUN: grep '@g_com = common hidden global i32 0' %t
+// RUN: grep '@g_def = hidden global i32 0' %t
+// RUN: grep '@g_ext = external global i32' %t
+// RUN: grep '@g_deferred = internal global' %t
+// RUN: grep 'declare void @f_ext()' %t
+// RUN: grep 'define internal void @f_deferred()' %t
+// RUN: grep 'define hidden i32 @f_def()' %t
int g_com;
int g_def = 0;
diff --git a/test/CodeGen/volatile-1.c b/test/CodeGen/volatile-1.c
index ac3b4c2e97b2..3203326ecebf 100644
--- a/test/CodeGen/volatile-1.c
+++ b/test/CodeGen/volatile-1.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -Wno-unused-value -emit-llvm < %s -o %t &&
-// RUN: grep volatile %t | count 145 &&
+// RUN: clang-cc -Wno-unused-value -emit-llvm < %s -o %t
+// RUN: grep volatile %t | count 145
// RUN: grep memcpy %t | count 4
volatile int i, j, k;
@@ -14,7 +14,7 @@ volatile struct S {
} a, b;
//void operator =(volatile struct S&o1, volatile struct S&o2) volatile;
-#include <stdio.h>
+int printf(const char *, ...);
int main() {
// A use.
diff --git a/test/CodeGen/volatile.c b/test/CodeGen/volatile.c
index e17669008a39..a0cc891ccd88 100644
--- a/test/CodeGen/volatile.c
+++ b/test/CodeGen/volatile.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -emit-llvm < %s -o %t &&
-// RUN: grep volatile %t | count 29 &&
+// RUN: clang-cc -emit-llvm < %s -o %t
+// RUN: grep volatile %t | count 29
// RUN: grep memcpy %t | count 7
// The number 29 comes from the current codegen for volatile loads;
diff --git a/test/CodeGen/x86.c b/test/CodeGen/x86.c
index be0930237c82..0420a4cd97de 100644
--- a/test/CodeGen/x86.c
+++ b/test/CodeGen/x86.c
@@ -1,11 +1,11 @@
-// RUN: clang-cc %s -triple=i686-pc-linux-gnu -emit-llvm -o - > %t1 &&
-// RUN: grep "ax" %t1 &&
-// RUN: grep "bx" %t1 &&
-// RUN: grep "cx" %t1 &&
-// RUN: grep "dx" %t1 &&
-// RUN: grep "di" %t1 &&
-// RUN: grep "si" %t1 &&
-// RUN: grep "st" %t1 &&
+// RUN: clang-cc %s -triple=i686-pc-linux-gnu -emit-llvm -o - > %t1
+// RUN: grep "ax" %t1
+// RUN: grep "bx" %t1
+// RUN: grep "cx" %t1
+// RUN: grep "dx" %t1
+// RUN: grep "di" %t1
+// RUN: grep "si" %t1
+// RUN: grep "st" %t1
// RUN: grep "st(1)" %t1
void test1() {
diff --git a/test/CodeGen/x86_32-arguments.c b/test/CodeGen/x86_32-arguments.c
index 78fb8342eebd..33f635c31ae1 100644
--- a/test/CodeGen/x86_32-arguments.c
+++ b/test/CodeGen/x86_32-arguments.c
@@ -1,14 +1,14 @@
-// RUN: clang-cc -fblocks -triple i386-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: grep 'define signext i8 @f0()' %t &&
-// RUN: grep 'define signext i16 @f1()' %t &&
-// RUN: grep 'define i32 @f2()' %t &&
-// RUN: grep 'define float @f3()' %t &&
-// RUN: grep 'define double @f4()' %t &&
-// RUN: grep 'define x86_fp80 @f5()' %t &&
-// RUN: grep 'define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8\* %a4)' %t &&
-// RUN: grep 'define void @f7(i32 %a0)' %t &&
-// RUN: grep 'define i64 @f8_1()' %t &&
-// RUN: grep 'define void @f8_2(i32 %a0.0, i32 %a0.1)' %t &&
+// RUN: clang-cc -fblocks -triple i386-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep 'define signext i8 @f0()' %t
+// RUN: grep 'define signext i16 @f1()' %t
+// RUN: grep 'define i32 @f2()' %t
+// RUN: grep 'define float @f3()' %t
+// RUN: grep 'define double @f4()' %t
+// RUN: grep 'define x86_fp80 @f5()' %t
+// RUN: grep 'define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8\* %a4)' %t
+// RUN: grep 'define void @f7(i32 %a0)' %t
+// RUN: grep 'define i64 @f8_1()' %t
+// RUN: grep 'define void @f8_2(i32 %a0.0, i32 %a0.1)' %t
char f0(void) {
return 0;
@@ -49,11 +49,11 @@ void f8_2(struct s8 a0) {}
// This should be passed just as s8.
-// RUN: grep 'define i64 @f9_1()' %t &&
+// RUN: grep 'define i64 @f9_1()' %t
// FIXME: llvm-gcc expands this, this may have some value for the
// backend in terms of optimization but doesn't change the ABI.
-// RUN: grep 'define void @f9_2(%.truct.s9\* byval %a0)' %t &&
+// RUN: grep 'define void @f9_2(%.truct.s9\* byval %a0)' %t
struct s9 {
int a : 17;
int b;
@@ -63,7 +63,7 @@ void f9_2(struct s9 a0) {}
// Return of small structures and unions
-// RUN: grep 'float @f10()' %t &&
+// RUN: grep 'float @f10()' %t
struct s10 {
union { };
float f;
@@ -71,12 +71,12 @@ struct s10 {
// Small vectors and 1 x {i64,double} are returned in registers
-// RUN: grep 'i32 @f11()' %t &&
-// RUN: grep -F 'void @f12(<2 x i32>* noalias sret %agg.result)' %t &&
-// RUN: grep 'i64 @f13()' %t &&
-// RUN: grep 'i64 @f14()' %t &&
-// RUN: grep '<2 x i64> @f15()' %t &&
-// RUN: grep '<2 x i64> @f16()' %t &&
+// RUN: grep 'i32 @f11()' %t
+// RUN: grep -F 'void @f12(<2 x i32>* noalias sret %agg.result)' %t
+// RUN: grep 'i64 @f13()' %t
+// RUN: grep 'i64 @f14()' %t
+// RUN: grep '<2 x i64> @f15()' %t
+// RUN: grep '<2 x i64> @f16()' %t
typedef short T11 __attribute__ ((vector_size (4)));
T11 f11(void) { while (1) {} }
typedef int T12 __attribute__ ((vector_size (8)));
@@ -93,12 +93,12 @@ T16 f16(void) { while (1) {} }
// And when the single element in a struct (but not for 64 and
// 128-bits).
-// RUN: grep 'i32 @f17()' %t &&
-// RUN: grep -F 'void @f18(%2* noalias sret %agg.result)' %t &&
-// RUN: grep -F 'void @f19(%3* noalias sret %agg.result)' %t &&
-// RUN: grep -F 'void @f20(%4* noalias sret %agg.result)' %t &&
-// RUN: grep -F 'void @f21(%5* noalias sret %agg.result)' %t &&
-// RUN: grep -F 'void @f22(%6* noalias sret %agg.result)' %t &&
+// RUN: grep 'i32 @f17()' %t
+// RUN: grep -F 'void @f18(%2* noalias sret %agg.result)' %t
+// RUN: grep -F 'void @f19(%3* noalias sret %agg.result)' %t
+// RUN: grep -F 'void @f20(%4* noalias sret %agg.result)' %t
+// RUN: grep -F 'void @f21(%5* noalias sret %agg.result)' %t
+// RUN: grep -F 'void @f22(%6* noalias sret %agg.result)' %t
struct { T11 a; } f17(void) { while (1) {} }
struct { T12 a; } f18(void) { while (1) {} }
struct { T13 a; } f19(void) { while (1) {} }
@@ -108,98 +108,97 @@ struct { T16 a; } f22(void) { while (1) {} }
// Single element structures are handled specially
-// RUN: grep -F 'float @f23()' %t &&
-// RUN: grep -F 'float @f24()' %t &&
-// RUN: grep -F 'float @f25()' %t &&
+// RUN: grep -F 'float @f23()' %t
+// RUN: grep -F 'float @f24()' %t
+// RUN: grep -F 'float @f25()' %t
struct { float a; } f23(void) { while (1) {} }
struct { float a[1]; } f24(void) { while (1) {} }
struct { struct {} a; struct { float a[1]; } b; } f25(void) { while (1) {} }
// Small structures are handled recursively
-// RUN: grep -F 'i32 @f26()' %t &&
-// RUN: grep 'void @f27(%.truct.s27\* noalias sret %agg.result)' %t &&
+// RUN: grep -F 'i32 @f26()' %t
+// RUN: grep 'void @f27(%.truct.s27\* noalias sret %agg.result)' %t
struct s26 { struct { char a, b; } a; struct { char a, b; } b; } f26(void) { while (1) {} }
struct s27 { struct { char a, b, c; } a; struct { char a; } b; } f27(void) { while (1) {} }
-// RUN: grep 'void @f28(%.truct.s28\* noalias sret %agg.result)' %t &&
+// RUN: grep 'void @f28(%.truct.s28\* noalias sret %agg.result)' %t
struct s28 { int a; int b[]; } f28(void) { while (1) {} }
-// RUN: grep 'define i16 @f29()' %t &&
+// RUN: grep 'define i16 @f29()' %t
struct s29 { struct { } a[1]; char b; char c; } f29(void) { while (1) {} }
-// RUN: grep 'define i16 @f30()' %t &&
+// RUN: grep 'define i16 @f30()' %t
struct s30 { char a; char b : 4; } f30(void) { while (1) {} }
-// RUN: grep 'define float @f31()' %t &&
+// RUN: grep 'define float @f31()' %t
struct s31 { char : 0; float b; char : 0; } f31(void) { while (1) {} }
-// RUN: grep 'define i32 @f32()' %t &&
+// RUN: grep 'define i32 @f32()' %t
struct s32 { char a; unsigned : 0; } f32(void) { while (1) {} }
-// RUN: grep 'define float @f33()' %t &&
+// RUN: grep 'define float @f33()' %t
struct s33 { float a; long long : 0; } f33(void) { while (1) {} }
-// RUN: grep 'define float @f34()' %t &&
+// RUN: grep 'define float @f34()' %t
struct s34 { struct { int : 0; } a; float b; } f34(void) { while (1) {} }
-// RUN: grep 'define i16 @f35()' %t &&
+// RUN: grep 'define i16 @f35()' %t
struct s35 { struct { int : 0; } a; char b; char c; } f35(void) { while (1) {} }
-// RUN: grep 'define i16 @f36()' %t &&
+// RUN: grep 'define i16 @f36()' %t
struct s36 { struct { int : 0; } a[2][10]; char b; char c; } f36(void) { while (1) {} }
-// RUN: grep 'define float @f37()' %t &&
+// RUN: grep 'define float @f37()' %t
struct s37 { float c[1][1]; } f37(void) { while (1) {} }
-// RUN: grep 'define void @f38(.struct.s38. noalias sret .agg.result)' %t &&
+// RUN: grep 'define void @f38(.struct.s38. noalias sret .agg.result)' %t
struct s38 { char a[3]; short b; } f38(void) { while (1) {} }
-// RUN: grep 'define void @f39(.struct.s39. byval align 16 .x)' %t &&
+// RUN: grep 'define void @f39(.struct.s39. byval align 16 .x)' %t
typedef int v39 __attribute((vector_size(16)));
struct s39 { v39 x; };
void f39(struct s39 x) {}
// <rdar://problem/7247671>
-// RUN: grep 'define i32 @f40()' %t &&
+// RUN: grep 'define i32 @f40()' %t
enum e40 { ec0 = 0 };
enum e40 f40(void) { }
-// RUN: grep 'define void ()\* @f41()' %t &&
+// RUN: grep 'define void ()\* @f41()' %t
typedef void (^vvbp)(void);
vvbp f41(void) { }
-// RUN: grep 'define i32 @f42()' %t &&
+// RUN: grep 'define i32 @f42()' %t
struct s42 { enum e40 f0; } f42(void) { }
-// RUN: grep 'define i64 @f43()' %t &&
+// RUN: grep 'define i64 @f43()' %t
struct s43 { enum e40 f0; int f1; } f43(void) { }
-// RUN: grep 'define i32 @f44()' %t &&
+// RUN: grep 'define i32 @f44()' %t
struct s44 { vvbp f0; } f44(void) { }
-// RUN: grep 'define i64 @f45()' %t &&
+// RUN: grep 'define i64 @f45()' %t
struct s45 { vvbp f0; int f1; } f45(void) { }
-// RUN: grep 'define void @f46(i32 %a0)' %t &&
+// RUN: grep 'define void @f46(i32 %a0)' %t
void f46(enum e40 a0) { }
-// RUN: grep 'define void @f47(void ()\* %a1)' %t &&
+// RUN: grep 'define void @f47(void ()\* %a1)' %t
void f47(vvbp a1) { }
-// RUN: grep 'define void @f48(i32 %a0.0)' %t &&
+// RUN: grep 'define void @f48(i32 %a0.0)' %t
struct s48 { enum e40 f0; };
void f48(struct s48 a0) { }
-// RUN: grep 'define void @f49(i32 %a0.0, i32 %a0.1)' %t &&
+// RUN: grep 'define void @f49(i32 %a0.0, i32 %a0.1)' %t
struct s49 { enum e40 f0; int f1; };
void f49(struct s49 a0) { }
-// RUN: grep 'define void @f50(void ()\* %a0.0)' %t &&
+// RUN: grep 'define void @f50(void ()\* %a0.0)' %t
struct s50 { vvbp f0; };
void f50(struct s50 a0) { }
-// RUN: grep 'define void @f51(void ()\* %a0.0, i32 %a0.1)' %t &&
+// RUN: grep 'define void @f51(void ()\* %a0.0, i32 %a0.1)' %t
struct s51 { vvbp f0; int f1; };
void f51(struct s51 a0) { }
-// RUN: true
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index 19f9cdaa2918..1a848ead356f 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -1,15 +1,15 @@
-// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: grep 'define signext i8 @f0()' %t &&
-// RUN: grep 'define signext i16 @f1()' %t &&
-// RUN: grep 'define i32 @f2()' %t &&
-// RUN: grep 'define float @f3()' %t &&
-// RUN: grep 'define double @f4()' %t &&
-// RUN: grep 'define x86_fp80 @f5()' %t &&
-// RUN: grep 'define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8\* %a4)' %t &&
-// RUN: grep 'define void @f7(i32 %a0)' %t &&
-// RUN: grep '.0 = type { i64, double }' %t &&
-// RUN: grep 'define .0 @f8_1()' %t &&
-// RUN: grep 'define void @f8_2(.0)' %t &&
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s
+// RUN: grep 'define signext i8 @f0()' %t
+// RUN: grep 'define signext i16 @f1()' %t
+// RUN: grep 'define i32 @f2()' %t
+// RUN: grep 'define float @f3()' %t
+// RUN: grep 'define double @f4()' %t
+// RUN: grep 'define x86_fp80 @f5()' %t
+// RUN: grep 'define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8\* %a4)' %t
+// RUN: grep 'define void @f7(i32 %a0)' %t
+// RUN: grep '.0 = type { i64, double }' %t
+// RUN: grep 'define .0 @f8_1()' %t
+// RUN: grep 'define void @f8_2(.0)' %t
char f0(void) {
return 0;
@@ -51,49 +51,48 @@ union u8 {
union u8 f8_1() { while (1) {} }
void f8_2(union u8 a0) {}
-// RUN: grep 'define i64 @f9()' %t &&
+// RUN: grep 'define i64 @f9()' %t
struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} }
-// RUN: grep 'define void @f10(i64)' %t &&
+// RUN: grep 'define void @f10(i64)' %t
struct s10 { int a; int b; int : 0; };
void f10(struct s10 a0) {}
-// RUN: grep 'define void @f11(.union.anon. noalias sret .agg.result)' %t &&
+// RUN: grep 'define void @f11(.union.anon. noalias sret .agg.result)' %t
union { long double a; float b; } f11() { while (1) {} }
-// RUN: grep 'define i64 @f12_0()' %t &&
-// RUN: grep 'define void @f12_1(i64)' %t &&
+// RUN: grep 'define i64 @f12_0()' %t
+// RUN: grep 'define void @f12_1(i64)' %t
struct s12 { int a __attribute__((aligned(16))); };
struct s12 f12_0(void) { while (1) {} }
void f12_1(struct s12 a0) {}
// Check that sret parameter is accounted for when checking available integer
// registers.
-// RUN: grep 'define void @f13(.struct.s13_0. noalias sret .agg.result, i32 .a, i32 .b, i32 .c, i32 .d, .struct.s13_1. byval .e, i32 .f)' %t &&
+// RUN: grep 'define void @f13(.struct.s13_0. noalias sret .agg.result, i32 .a, i32 .b, i32 .c, i32 .d, .struct.s13_1. byval .e, i32 .f)' %t
struct s13_0 { long long f0[3]; };
struct s13_1 { long long f0[2]; };
struct s13_0 f13(int a, int b, int c, int d,
struct s13_1 e, int f) { while (1) {} }
-// RUN: grep 'define void @f14(.*, i8 signext .X)' %t &&
+// RUN: grep 'define void @f14(.*, i8 signext .X)' %t
void f14(int a, int b, int c, int d, int e, int f,
char X) {}
-// RUN: grep 'define void @f15(.*, i8\* .X)' %t &&
+// RUN: grep 'define void @f15(.*, i8\* .X)' %t
void f15(int a, int b, int c, int d, int e, int f,
void *X) {}
-// RUN: grep 'define void @f16(.*, float .X)' %t &&
+// RUN: grep 'define void @f16(.*, float .X)' %t
void f16(float a, float b, float c, float d, float e, float f, float g, float h,
float X) {}
-// RUN: grep 'define void @f17(.*, x86_fp80 .X)' %t &&
+// RUN: grep 'define void @f17(.*, x86_fp80 .X)' %t
void f17(float a, float b, float c, float d, float e, float f, float g, float h,
long double X) {}
// Check for valid coercion.
-// RUN: grep '.. = bitcast i64. .* to .struct.f18_s0.' %t &&
-// RUN: grep '.. = load .struct.f18_s0. .., align 1' %t &&
-// RUN: grep 'store .struct.f18_s0 .., .struct.f18_s0. .f18_arg1' %t &&
+// RUN: grep '.. = bitcast i64. .* to .struct.f18_s0.' %t
+// RUN: grep '.. = load .struct.f18_s0. .., align 1' %t
+// RUN: grep 'store .struct.f18_s0 .., .struct.f18_s0. .f18_arg1' %t
struct f18_s0 { int f0; };
void f18(int a, struct f18_s0 f18_arg1) { while (1) {} }
-// RUN: true
diff --git a/test/CodeGenCXX/PR5050-constructor-conversion.cpp b/test/CodeGenCXX/PR5050-constructor-conversion.cpp
index e5f722c513de..c0b53d5f6e55 100644
--- a/test/CodeGenCXX/PR5050-constructor-conversion.cpp
+++ b/test/CodeGenCXX/PR5050-constructor-conversion.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
struct A { A(const A&, int i1 = 1); };
diff --git a/test/CodeGenCXX/array-construction.cpp b/test/CodeGenCXX/array-construction.cpp
index 5b6bc2e5b511..2f82872d6c9e 100644
--- a/test/CodeGenCXX/array-construction.cpp
+++ b/test/CodeGenCXX/array-construction.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/array-operator-delete-call.cpp b/test/CodeGenCXX/array-operator-delete-call.cpp
new file mode 100644
index 000000000000..c23d33632a38
--- /dev/null
+++ b/test/CodeGenCXX/array-operator-delete-call.cpp
@@ -0,0 +1,63 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+
+extern "C" int printf(...);
+
+int count;
+
+struct S {
+ S() : iS (++count) { printf("S::S(%d)\n", iS); }
+ ~S() { printf("S::~S(%d)\n", iS); }
+ int iS;
+};
+
+struct V {
+ V() : iV (++count) { printf("V::V(%d)\n", iV); }
+ virtual ~V() { printf("V::~V(%d)\n", iV); }
+ int iV;
+};
+
+struct COST
+{
+ S *cost;
+ V *vcost;
+ unsigned *cost_val;
+
+ ~COST();
+ COST();
+};
+
+
+COST::COST()
+{
+ cost = new S[3];
+ vcost = new V[4];
+ cost_val = new unsigned[10];
+}
+
+COST::~COST()
+{
+ if (cost) {
+ delete [] cost;
+ }
+ if (vcost) {
+ delete [] vcost;
+ }
+ if (cost_val)
+ delete [] cost_val;
+}
+
+COST c1;
+
+int main()
+{
+ COST c3;
+}
+COST c2;
+
+// CHECK-LP64: call __ZdaPv
+
+// CHECK-LP32: call L__ZdaPv
+
diff --git a/test/CodeGenCXX/array-value-initialize.cpp b/test/CodeGenCXX/array-value-initialize.cpp
new file mode 100644
index 000000000000..f041bc584b12
--- /dev/null
+++ b/test/CodeGenCXX/array-value-initialize.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-cc -emit-llvm -o - %s
+
+// PR5463
+extern "C" int printf(...);
+
+struct S {
+ double filler;
+};
+
+struct Foo {
+ Foo(void) : bar_(), dbar_(), sbar_() {
+ for (int i = 0; i < 5; i++) {
+ printf("bar_[%d] = %d\n", i, bar_[i]);
+ printf("dbar_[%d] = %f\n", i, dbar_[i]);
+ printf("sbar_[%d].filler = %f\n", i, sbar_[i].filler);
+ }
+ }
+
+ int bar_[5];
+ double dbar_[5];
+ S sbar_[5];
+};
+
+int main(void)
+{
+ Foo a;
+}
+
diff --git a/test/CodeGenCXX/assign-operator.cpp b/test/CodeGenCXX/assign-operator.cpp
new file mode 100644
index 000000000000..3e0be4519438
--- /dev/null
+++ b/test/CodeGenCXX/assign-operator.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-cc %s -emit-llvm-only -verify
+
+class x {
+int operator=(int);
+};
+void a() {
+ x a;
+ a = 1u;
+}
diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp
index 8077b7839d88..695e9e72f1a1 100644
--- a/test/CodeGenCXX/attr.cpp
+++ b/test/CodeGenCXX/attr.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -O0 -S %s -o %t.s &&
+// RUN: clang-cc -triple x86_64-apple-darwin -O0 -S %s -o %t.s
// RUN: FileCheck --input-file=%t.s %s
int foo() __attribute__((aligned(1024)));
diff --git a/test/CodeGenCXX/call-arg-zero-temp.cpp b/test/CodeGenCXX/call-arg-zero-temp.cpp
index 2c44f69d975e..e066927ad702 100644
--- a/test/CodeGenCXX/call-arg-zero-temp.cpp
+++ b/test/CodeGenCXX/call-arg-zero-temp.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/cast-conversion.cpp b/test/CodeGenCXX/cast-conversion.cpp
index f571f549d094..fa8487ac66b9 100644
--- a/test/CodeGenCXX/cast-conversion.cpp
+++ b/test/CodeGenCXX/cast-conversion.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
struct A {
A(int);
diff --git a/test/CodeGenCXX/class-layout.cpp b/test/CodeGenCXX/class-layout.cpp
index 7255d3e4f94d..7663d2e541b2 100644
--- a/test/CodeGenCXX/class-layout.cpp
+++ b/test/CodeGenCXX/class-layout.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -emit-llvm -o %t &&
+// RUN: clang-cc %s -emit-llvm -o %t
// An extra byte shoudl be allocated for an empty class.
// RUN: grep '%.truct.A = type { i8 }' %t
diff --git a/test/CodeGenCXX/constructor-conversion.cpp b/test/CodeGenCXX/constructor-conversion.cpp
index 980b230118d8..dcc9535315ab 100644
--- a/test/CodeGenCXX/constructor-conversion.cpp
+++ b/test/CodeGenCXX/constructor-conversion.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/constructor-default-arg.cpp b/test/CodeGenCXX/constructor-default-arg.cpp
index 7e6a7cd8f71a..c494149d1110 100644
--- a/test/CodeGenCXX/constructor-default-arg.cpp
+++ b/test/CodeGenCXX/constructor-default-arg.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/constructor-for-array-members.cpp b/test/CodeGenCXX/constructor-for-array-members.cpp
index fbb13e0aa3c2..5160a8975488 100644
--- a/test/CodeGenCXX/constructor-for-array-members.cpp
+++ b/test/CodeGenCXX/constructor-for-array-members.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/constructor-template.cpp b/test/CodeGenCXX/constructor-template.cpp
index 8c4f2c912709..66ec9eac212c 100644
--- a/test/CodeGenCXX/constructor-template.cpp
+++ b/test/CodeGenCXX/constructor-template.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
// PR4826
struct A {
diff --git a/test/CodeGenCXX/conversion-function.cpp b/test/CodeGenCXX/conversion-function.cpp
index 0bfd4af7e265..c93587675ba1 100644
--- a/test/CodeGenCXX/conversion-function.cpp
+++ b/test/CodeGenCXX/conversion-function.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
struct S {
diff --git a/test/CodeGenCXX/convert-to-fptr.cpp b/test/CodeGenCXX/convert-to-fptr.cpp
index c0bd2f7b856e..7cc8c08444aa 100644
--- a/test/CodeGenCXX/convert-to-fptr.cpp
+++ b/test/CodeGenCXX/convert-to-fptr.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-assign-synthesis-1.cpp b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
index d4a93afefbfa..14fbe30703d3 100644
--- a/test/CodeGenCXX/copy-assign-synthesis-1.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-assign-synthesis.cpp b/test/CodeGenCXX/copy-assign-synthesis.cpp
index f9baa8f03f3c..65a84f414a93 100644
--- a/test/CodeGenCXX/copy-assign-synthesis.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
+// RUN: clang-cc -emit-llvm -o %t %s
// RUN: grep "_ZN1XaSERK1X" %t | count 0
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-constructor-elim.cpp b/test/CodeGenCXX/copy-constructor-elim.cpp
index daef92cdb767..953effe77af1 100644
--- a/test/CodeGenCXX/copy-constructor-elim.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim.cpp
@@ -1,7 +1,6 @@
-// RUN: clang-cc -emit-llvm -o %t %s &&
-// RUN: grep "_ZN1CC1ERK1C" %t | count 0 &&
-// RUN: grep "_ZN1SC1ERK1S" %t | count 0 &&
-// RUN: true
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: grep "_ZN1CC1ERK1C" %t | count 0
+// RUN: grep "_ZN1SC1ERK1S" %t | count 0
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp
index 47971afe61d4..3b8f7821abcf 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
@@ -45,6 +44,8 @@ struct X : M, N, P { // ...
const char *name;
unsigned bf1 : 8;
unsigned bf2 : 16;
+ int arr[2];
+ _Complex float complex;
union {
int au_i1;
diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp
new file mode 100644
index 000000000000..b89435a99044
--- /dev/null
+++ b/test/CodeGenCXX/debug-info.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -emit-llvm-only -g
+template<typename T> struct Identity {
+ typedef T Type;
+};
+
+void f(Identity<int>::Type a) {}
+void f(Identity<int> a) {}
+void f(int& a) { }
+
+template<typename T> struct A {
+ A<T> *next;
+};
+void f(A<int>) { }
diff --git a/test/CodeGenCXX/decl-ref-init.cpp b/test/CodeGenCXX/decl-ref-init.cpp
index 27d200f4635b..fd93b7b21e04 100644
--- a/test/CodeGenCXX/decl-ref-init.cpp
+++ b/test/CodeGenCXX/decl-ref-init.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
struct A {};
diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp
index 8385aff6291c..0ec5b582c95b 100644
--- a/test/CodeGenCXX/default-arg-temps.cpp
+++ b/test/CodeGenCXX/default-arg-temps.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 &&
+// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9
struct T {
T();
@@ -14,8 +14,8 @@ public:
};
void g() {
- // RUN: grep "call void @_ZN1TC1Ev" %t | count 4 &&
- // RUN: grep "call void @_ZN1TD1Ev" %t | count 4 &&
+ // RUN: grep "call void @_ZN1TC1Ev" %t | count 4
+ // RUN: grep "call void @_ZN1TD1Ev" %t | count 4
f();
f();
diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp
new file mode 100644
index 000000000000..5028ce99c7b7
--- /dev/null
+++ b/test/CodeGenCXX/default-arguments.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10
+
+// PR5484
+namespace PR5484 {
+struct A { };
+extern A a;
+
+void f(const A & = a);
+
+void g() {
+ f();
+}
+}
diff --git a/test/CodeGenCXX/default-constructor-default-argument.cpp b/test/CodeGenCXX/default-constructor-default-argument.cpp
new file mode 100644
index 000000000000..f53732e471fe
--- /dev/null
+++ b/test/CodeGenCXX/default-constructor-default-argument.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
+
+// Check that call to constructor for struct A is generated correctly.
+struct A { A(int x = 2); };
+struct B : public A {};
+B x;
+
+// CHECK: call void @_ZN1AC1Ei
diff --git a/test/CodeGenCXX/default-constructor-for-members.cpp b/test/CodeGenCXX/default-constructor-for-members.cpp
index 2d04bc941427..d972d63d3cbc 100644
--- a/test/CodeGenCXX/default-constructor-for-members.cpp
+++ b/test/CodeGenCXX/default-constructor-for-members.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/default-destructor-synthesis.cpp b/test/CodeGenCXX/default-destructor-synthesis.cpp
index 9cc802c85dfa..fef9c03d7ac1 100644
--- a/test/CodeGenCXX/default-destructor-synthesis.cpp
+++ b/test/CodeGenCXX/default-destructor-synthesis.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -O0 -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 -input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -O0 -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 -input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/delete-two-arg.cpp b/test/CodeGenCXX/delete-two-arg.cpp
new file mode 100644
index 000000000000..a5b18ba06fc3
--- /dev/null
+++ b/test/CodeGenCXX/delete-two-arg.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-cc -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s
+
+struct A { void operator delete(void*,__typeof(sizeof(int))); int x; };
+void a(A* x) { delete x; }
+
+// CHECK: call void @_ZN1AdlEPvj(i8* %0, i32 4)
diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp
index 9e3feefefeda..78c83cf0df62 100644
--- a/test/CodeGenCXX/delete.cpp
+++ b/test/CodeGenCXX/delete.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -emit-llvm -o %t &&
+// RUN: clang-cc %s -emit-llvm -o %t
void t1(int *a) {
delete a;
diff --git a/test/CodeGenCXX/derived-to-base-conv.cpp b/test/CodeGenCXX/derived-to-base-conv.cpp
index 0c890195119f..70948b0ff933 100644
--- a/test/CodeGenCXX/derived-to-base-conv.cpp
+++ b/test/CodeGenCXX/derived-to-base-conv.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
extern "C" void exit(int);
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index 44d2b2936864..a196c13f8f42 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -28,3 +28,17 @@ class A1 {
};
template<> A1<char>::~A1();
+
+// PR5529
+namespace PR5529 {
+ struct A {
+ ~A();
+ };
+
+ A::~A() { }
+ struct B : A {
+ virtual ~B();
+ };
+
+ B::~B() {}
+}
diff --git a/test/CodeGenCXX/dyncast.cpp b/test/CodeGenCXX/dyncast.cpp
new file mode 100644
index 000000000000..4719f80a5b41
--- /dev/null
+++ b/test/CodeGenCXX/dyncast.cpp
@@ -0,0 +1,414 @@
+// RUN: clang-cc -I%S -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t.ll
+// RUN: FileCheck -check-prefix LL --input-file=%t.ll %s
+
+#include <typeinfo>
+
+class test1_A { virtual void f() { } };
+class test1_B { virtual void g() { } };
+class test1_D : public virtual test1_A, private test1_B {};
+class test1_E : public test1_D, public test1_B {};
+class test1_F : public test1_E, public test1_D {};
+
+extern test1_D test1_d;
+extern test1_F test1_f;
+
+extern "C" int printf(const char *str...);
+
+#define S(V, N) if (V) printf("PASS: %d\n", N); else printf("FAIL: %d\n", N)
+
+void test1() {
+ test1_B* bp = (test1_B*)&test1_d;
+ test1_A* ap = &test1_d;
+ // This throws
+ // test1_D& dr = dynamic_cast<D&>(*bp);
+ test1_D* dp = dynamic_cast<test1_D*>(bp);
+ S(dp == 0, 1);
+ ap = dynamic_cast<test1_A*>(bp);
+ S(ap == 0, 2);
+ bp = dynamic_cast<test1_B*>(ap);
+ S(bp == 0, 3);
+ ap = dynamic_cast<test1_A*>(&test1_d);
+ S(ap != 0, 4);
+ // FIXME: Doesn't work yet, gcc fails this at compile time. We'd need access
+ // control for this to work.
+ // bp = dynamic_cast<test1_B*>(&test1_d);
+ // S(bp == 0, 5);
+ {
+ test1_A* ap = &test1_f;
+ S(ap != 0, 6);
+ test1_D* dp = dynamic_cast<test1_D*>(ap);
+ S(dp == 0, 7);
+ // cast from virtual base
+ test1_E* ep1 = dynamic_cast<test1_E*>(ap);
+ S(ep1 != 0, 8);
+ }
+ dp = dynamic_cast<test1_D*>(&test1_d);
+ S(dp == &test1_d, 9);
+ const test1_D *cdp = dynamic_cast<const test1_D*>(&test1_d);
+ S(cdp == &test1_d, 10);
+ dp = dynamic_cast<test1_D*>((test1_A*)0);
+ S(dp == 0, 11);
+ ap = dynamic_cast<test1_A*>(&test1_d);
+ S(ap == (test1_A*)&test1_d, 12);
+ test1_E* ep = dynamic_cast<test1_E*>(&test1_f);
+ S(ep == (test1_E*)&test1_f, 13);
+ void *vp = dynamic_cast<void*>(ap);
+ S(vp == &test1_d, 14);
+ const void *cvp = dynamic_cast<const void*>(ap);
+ S(cvp == &test1_d, 15);
+}
+
+// CHECK-LL: define void @_Z5test1v() nounwind {
+// CHECK-LL-NEXT:entry:
+// CHECK-LL-NEXT: %bp = alloca %class.test1_A*, align 8
+// CHECK-LL-NEXT: %ap = alloca %class.test1_A*, align 8
+// CHECK-LL-NEXT: %dp = alloca %class.test1_D*, align 8
+// CHECK-LL-NEXT: %ap37 = alloca %class.test1_A*, align 8
+// CHECK-LL-NEXT: %dp53 = alloca %class.test1_D*, align 8
+// CHECK-LL-NEXT: %ep1 = alloca %class.test1_E*, align 8
+// CHECK-LL-NEXT: %cdp = alloca %class.test1_D*, align 8
+// CHECK-LL-NEXT: %ep = alloca %class.test1_E*, align 8
+// CHECK-LL-NEXT: %vp = alloca i8*, align 8
+// CHECK-LL-NEXT: %cvp = alloca i8*, align 8
+// CHECK-LL-NEXT: br i1 false, label %cast.null, label %cast.notnull
+// CHECK-LL: cast.notnull:
+// CHECK-LL-NEXT: br label %cast.end
+// CHECK-LL: cast.null:
+// CHECK-LL-NEXT: br label %cast.end
+// CHECK-LL: cast.end:
+// CHECK-LL-NEXT: %0 = phi %class.test1_A* [ bitcast (%class.test1_D* @test1_d to %class.test1_A*), %cast.notnull ], [ null, %cast.null ]
+// CHECK-LL-NEXT: store %class.test1_A* %0, %class.test1_A** %bp
+// CHECK-LL-NEXT: br i1 false, label %cast.null2, label %cast.notnull1
+// CHECK-LL: cast.notnull1:
+// CHECK-LL-NEXT: %vtable = load i8** bitcast (%class.test1_D* @test1_d to i8**)
+// CHECK-LL-NEXT: %vbase.offset.ptr = getelementptr i8* %vtable, i64 -24
+// CHECK-LL-NEXT: %1 = bitcast i8* %vbase.offset.ptr to i64*
+// CHECK-LL-NEXT: %vbase.offset = load i64* %1
+// CHECK-LL-NEXT: %add.ptr = getelementptr i8* getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0), i64 %vbase.offset
+// CHECK-LL-NEXT: %2 = bitcast i8* %add.ptr to %class.test1_A*
+// CHECK-LL-NEXT: br label %cast.end3
+// CHECK-LL: cast.null2:
+// CHECK-LL-NEXT: br label %cast.end3
+// CHECK-LL: cast.end3:
+// CHECK-LL-NEXT: %3 = phi %class.test1_A* [ %2, %cast.notnull1 ], [ null, %cast.null2 ]
+// CHECK-LL-NEXT: store %class.test1_A* %3, %class.test1_A** %ap
+// CHECK-LL-NEXT: %tmp = load %class.test1_A** %bp
+// CHECK-LL-NEXT: %4 = icmp ne %class.test1_A* %tmp, null
+// CHECK-LL-NEXT: br i1 %4, label %5, label %9
+// CHECK-LL: ; <label>:5
+// CHECK-LL-NEXT: %6 = bitcast %class.test1_A* %tmp to i8*
+// CHECK-LL-NEXT: %7 = call i8* @__dynamic_cast(i8* %6, i8* bitcast (i8** @_ZTI7test1_B to i8*), i8* bitcast (i8** @_ZTI7test1_D to i8*), i64 -1)
+// CHECK-LL-NEXT: %8 = bitcast i8* %7 to %class.test1_D*
+// CHECK-LL-NEXT: br label %10
+// CHECK-LL: ; <label>:9
+// CHECK-LL-NEXT: br label %10
+// CHECK-LL: ; <label>:10
+// CHECK-LL-NEXT: %11 = phi %class.test1_D* [ %8, %5 ], [ null, %9 ]
+// CHECK-LL-NEXT: store %class.test1_D* %11, %class.test1_D** %dp
+// CHECK-LL-NEXT: %tmp4 = load %class.test1_D** %dp
+// CHECK-LL-NEXT: %cmp = icmp eq %class.test1_D* %tmp4, null
+// CHECK-LL-NEXT: br i1 %cmp, label %if.then, label %if.else
+// CHECK-LL: if.then:
+// CHECK-LL-NEXT: %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 1)
+// CHECK-LL-NEXT: br label %if.end
+// CHECK-LL: if.else:
+// CHECK-LL-NEXT: %call5 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 1)
+// CHECK-LL-NEXT: br label %if.end
+// CHECK-LL: if.end:
+// CHECK-LL-NEXT: %tmp6 = load %class.test1_A** %bp
+// CHECK-LL-NEXT: %12 = icmp ne %class.test1_A* %tmp6, null
+// CHECK-LL-NEXT: br i1 %12, label %13, label %17
+// CHECK-LL: ; <label>:13
+// CHECK-LL-NEXT: %14 = bitcast %class.test1_A* %tmp6 to i8*
+// CHECK-LL-NEXT: %15 = call i8* @__dynamic_cast(i8* %14, i8* bitcast (i8** @_ZTI7test1_B to i8*), i8* bitcast (i8** @_ZTI7test1_A to i8*), i64 -1)
+// CHECK-LL-NEXT: %16 = bitcast i8* %15 to %class.test1_A*
+// CHECK-LL-NEXT: br label %18
+// CHECK-LL: ; <label>:17
+// CHECK-LL-NEXT: br label %18
+// CHECK-LL: ; <label>:18
+// CHECK-LL-NEXT: %19 = phi %class.test1_A* [ %16, %13 ], [ null, %17 ]
+// CHECK-LL-NEXT: store %class.test1_A* %19, %class.test1_A** %ap
+// CHECK-LL-NEXT: %tmp7 = load %class.test1_A** %ap
+// CHECK-LL-NEXT: %cmp8 = icmp eq %class.test1_A* %tmp7, null
+// CHECK-LL-NEXT: br i1 %cmp8, label %if.then9, label %if.else11
+// CHECK-LL: if.then9:
+// CHECK-LL-NEXT: %call10 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 2)
+// CHECK-LL-NEXT: br label %if.end13
+// CHECK-LL: if.else11:
+// CHECK-LL-NEXT: %call12 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 2)
+// CHECK-LL-NEXT: br label %if.end13
+// CHECK-LL: if.end13:
+// CHECK-LL-NEXT: %tmp14 = load %class.test1_A** %ap
+// CHECK-LL-NEXT: %20 = icmp ne %class.test1_A* %tmp14, null
+// CHECK-LL-NEXT: br i1 %20, label %21, label %25
+// CHECK-LL: ; <label>:21
+// CHECK-LL-NEXT: %22 = bitcast %class.test1_A* %tmp14 to i8*
+// CHECK-LL-NEXT: %23 = call i8* @__dynamic_cast(i8* %22, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_B to i8*), i64 -1)
+// CHECK-LL-NEXT: %24 = bitcast i8* %23 to %class.test1_A*
+// CHECK-LL-NEXT: br label %26
+// CHECK-LL: ; <label>:25
+// CHECK-LL-NEXT: br label %26
+// CHECK-LL: ; <label>:26
+// CHECK-LL-NEXT: %27 = phi %class.test1_A* [ %24, %21 ], [ null, %25 ]
+// CHECK-LL-NEXT: store %class.test1_A* %27, %class.test1_A** %bp
+// CHECK-LL-NEXT: %tmp15 = load %class.test1_A** %bp
+// CHECK-LL-NEXT: %cmp16 = icmp eq %class.test1_A* %tmp15, null
+// CHECK-LL-NEXT: br i1 %cmp16, label %if.then17, label %if.else19
+// CHECK-LL: if.then17:
+// CHECK-LL-NEXT: %call18 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 3)
+// CHECK-LL-NEXT: br label %if.end21
+// CHECK-LL: if.else19:
+// CHECK-LL-NEXT: %call20 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 3)
+// CHECK-LL-NEXT: br label %if.end21
+// CHECK-LL: if.end21:
+// CHECK-LL-NEXT: br i1 false, label %cast.null27, label %cast.notnull22
+// CHECK-LL: cast.notnull22:
+// CHECK-LL-NEXT: %vtable23 = load i8** bitcast (%class.test1_D* @test1_d to i8**)
+// CHECK-LL-NEXT: %vbase.offset.ptr24 = getelementptr i8* %vtable23, i64 -24
+// CHECK-LL-NEXT: %28 = bitcast i8* %vbase.offset.ptr24 to i64*
+// CHECK-LL-NEXT: %vbase.offset25 = load i64* %28
+// CHECK-LL-NEXT: %add.ptr26 = getelementptr i8* getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0), i64 %vbase.offset25
+// CHECK-LL-NEXT: %29 = bitcast i8* %add.ptr26 to %class.test1_A*
+// CHECK-LL-NEXT: br label %cast.end28
+// CHECK-LL: cast.null27:
+// CHECK-LL-NEXT: br label %cast.end28
+// CHECK-LL: cast.end28:
+// CHECK-LL-NEXT: %30 = phi %class.test1_A* [ %29, %cast.notnull22 ], [ null, %cast.null27 ]
+// CHECK-LL-NEXT: store %class.test1_A* %30, %class.test1_A** %ap
+// CHECK-LL-NEXT: %tmp29 = load %class.test1_A** %ap
+// CHECK-LL-NEXT: %cmp30 = icmp ne %class.test1_A* %tmp29, null
+// CHECK-LL-NEXT: br i1 %cmp30, label %if.then31, label %if.else33
+// CHECK-LL: if.then31:
+// CHECK-LL-NEXT: %call32 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 4)
+// CHECK-LL-NEXT: br label %if.end35
+// CHECK-LL: if.else33:
+// CHECK-LL-NEXT: %call34 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 4)
+// CHECK-LL-NEXT: br label %if.end35
+// CHECK-LL: if.end35:
+// CHECK-LL-NEXT: br i1 false, label %cast.null43, label %cast.notnull38
+// CHECK-LL: cast.notnull38:
+// CHECK-LL-NEXT: %vtable39 = load i8** bitcast (%class.test1_F* @test1_f to i8**)
+// CHECK-LL-NEXT: %vbase.offset.ptr40 = getelementptr i8* %vtable39, i64 -24
+// CHECK-LL-NEXT: %31 = bitcast i8* %vbase.offset.ptr40 to i64*
+// CHECK-LL-NEXT: %vbase.offset41 = load i64* %31
+// CHECK-LL-NEXT: %add.ptr42 = getelementptr i8* getelementptr inbounds (%class.test1_F* @test1_f, i32 0, i32 0, i32 0), i64 %vbase.offset41
+// CHECK-LL-NEXT: %32 = bitcast i8* %add.ptr42 to %class.test1_A*
+// CHECK-LL-NEXT: br label %cast.end44
+// CHECK-LL: cast.null43:
+// CHECK-LL-NEXT: br label %cast.end44
+// CHECK-LL: cast.end44:
+// CHECK-LL-NEXT: %33 = phi %class.test1_A* [ %32, %cast.notnull38 ], [ null, %cast.null43 ]
+// CHECK-LL-NEXT: store %class.test1_A* %33, %class.test1_A** %ap37
+// CHECK-LL-NEXT: %tmp45 = load %class.test1_A** %ap37
+// CHECK-LL-NEXT: %cmp46 = icmp ne %class.test1_A* %tmp45, null
+// CHECK-LL-NEXT: br i1 %cmp46, label %if.then47, label %if.else49
+// CHECK-LL: if.then47:
+// CHECK-LL-NEXT: %call48 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 6)
+// CHECK-LL-NEXT: br label %if.end51
+// CHECK-LL: if.else49:
+// CHECK-LL-NEXT: %call50 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 6)
+// CHECK-LL-NEXT: br label %if.end51
+// CHECK-LL: if.end51:
+// CHECK-LL-NEXT: %tmp54 = load %class.test1_A** %ap37
+// CHECK-LL-NEXT: %34 = icmp ne %class.test1_A* %tmp54, null
+// CHECK-LL-NEXT: br i1 %34, label %35, label %39
+// CHECK-LL: ; <label>:35
+// CHECK-LL-NEXT: %36 = bitcast %class.test1_A* %tmp54 to i8*
+// CHECK-LL-NEXT: %37 = call i8* @__dynamic_cast(i8* %36, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_D to i8*), i64 -1)
+// CHECK-LL-NEXT: %38 = bitcast i8* %37 to %class.test1_D*
+// CHECK-LL-NEXT: br label %40
+// CHECK-LL: ; <label>:39
+// CHECK-LL-NEXT: br label %40
+// CHECK-LL: ; <label>:40
+// CHECK-LL-NEXT: %41 = phi %class.test1_D* [ %38, %35 ], [ null, %39 ]
+// CHECK-LL-NEXT: store %class.test1_D* %41, %class.test1_D** %dp53
+// CHECK-LL-NEXT: %tmp55 = load %class.test1_D** %dp53
+// CHECK-LL-NEXT: %cmp56 = icmp eq %class.test1_D* %tmp55, null
+// CHECK-LL-NEXT: br i1 %cmp56, label %if.then57, label %if.else59
+// CHECK-LL: if.then57:
+// CHECK-LL-NEXT: %call58 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 7)
+// CHECK-LL-NEXT: br label %if.end61
+// CHECK-LL: if.else59:
+// CHECK-LL-NEXT: %call60 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 7)
+// CHECK-LL-NEXT: br label %if.end61
+// CHECK-LL: if.end61:
+// CHECK-LL-NEXT: %tmp63 = load %class.test1_A** %ap37
+// CHECK-LL-NEXT: %42 = icmp ne %class.test1_A* %tmp63, null
+// CHECK-LL-NEXT: br i1 %42, label %43, label %47
+// CHECK-LL: ; <label>:43
+// CHECK-LL-NEXT: %44 = bitcast %class.test1_A* %tmp63 to i8*
+// CHECK-LL-NEXT: %45 = call i8* @__dynamic_cast(i8* %44, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_E to i8*), i64 -1)
+// CHECK-LL-NEXT: %46 = bitcast i8* %45 to %class.test1_E*
+// CHECK-LL-NEXT: br label %48
+// CHECK-LL: ; <label>:47
+// CHECK-LL-NEXT: br label %48
+// CHECK-LL: ; <label>:48
+// CHECK-LL-NEXT: %49 = phi %class.test1_E* [ %46, %43 ], [ null, %47 ]
+// CHECK-LL-NEXT: store %class.test1_E* %49, %class.test1_E** %ep1
+// CHECK-LL-NEXT: %tmp64 = load %class.test1_E** %ep1
+// CHECK-LL-NEXT: %cmp65 = icmp ne %class.test1_E* %tmp64, null
+// CHECK-LL-NEXT: br i1 %cmp65, label %if.then66, label %if.else68
+// CHECK-LL: if.then66:
+// CHECK-LL-NEXT: %call67 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 8)
+// CHECK-LL-NEXT: br label %if.end70
+// CHECK-LL: if.else68:
+// CHECK-LL-NEXT: %call69 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 8)
+// CHECK-LL-NEXT: br label %if.end70
+// CHECK-LL: if.end70:
+// CHECK-LL-NEXT: store %class.test1_D* @test1_d, %class.test1_D** %dp
+// CHECK-LL-NEXT: %tmp71 = load %class.test1_D** %dp
+// CHECK-LL-NEXT: %cmp72 = icmp eq %class.test1_D* %tmp71, @test1_d
+// CHECK-LL-NEXT: br i1 %cmp72, label %if.then73, label %if.else75
+// CHECK-LL: if.then73:
+// CHECK-LL-NEXT: %call74 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 9)
+// CHECK-LL-NEXT: br label %if.end77
+// CHECK-LL: if.else75:
+// CHECK-LL-NEXT: %call76 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 9)
+// CHECK-LL-NEXT: br label %if.end77
+// CHECK-LL: if.end77:
+// CHECK-LL-NEXT: store %class.test1_D* @test1_d, %class.test1_D** %cdp
+// CHECK-LL-NEXT: %tmp79 = load %class.test1_D** %cdp
+// CHECK-LL-NEXT: %cmp80 = icmp eq %class.test1_D* %tmp79, @test1_d
+// CHECK-LL-NEXT: br i1 %cmp80, label %if.then81, label %if.else83
+// CHECK-LL: if.then81:
+// CHECK-LL-NEXT: %call82 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 10)
+// CHECK-LL-NEXT: br label %if.end85
+// CHECK-LL: if.else83:
+// CHECK-LL-NEXT: %call84 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 10)
+// CHECK-LL-NEXT: br label %if.end85
+// CHECK-LL: if.end85:
+// CHECK-LL-NEXT: br i1 false, label %50, label %53
+// CHECK-LL: ; <label>:50
+// CHECK-LL-NEXT: %51 = call i8* @__dynamic_cast(i8* null, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_D to i8*), i64 -1)
+// CHECK-LL-NEXT: %52 = bitcast i8* %51 to %class.test1_D*
+// CHECK-LL-NEXT: br label %54
+// CHECK-LL: ; <label>:53
+// CHECK-LL-NEXT: br label %54
+// CHECK-LL: ; <label>:54
+// CHECK-LL-NEXT: %55 = phi %class.test1_D* [ %52, %50 ], [ null, %53 ]
+// CHECK-LL-NEXT: store %class.test1_D* %55, %class.test1_D** %dp
+// CHECK-LL-NEXT: %tmp86 = load %class.test1_D** %dp
+// CHECK-LL-NEXT: %cmp87 = icmp eq %class.test1_D* %tmp86, null
+// CHECK-LL-NEXT: br i1 %cmp87, label %if.then88, label %if.else90
+// CHECK-LL: if.then88:
+// CHECK-LL-NEXT: %call89 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 11)
+// CHECK-LL-NEXT: br label %if.end92
+// CHECK-LL: if.else90:
+// CHECK-LL-NEXT: %call91 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 11)
+// CHECK-LL-NEXT: br label %if.end92
+// CHECK-LL: if.end92:
+// CHECK-LL-NEXT: br i1 false, label %cast.null98, label %cast.notnull93
+// CHECK-LL: cast.notnull93:
+// CHECK-LL-NEXT: %vtable94 = load i8** bitcast (%class.test1_D* @test1_d to i8**)
+// CHECK-LL-NEXT: %vbase.offset.ptr95 = getelementptr i8* %vtable94, i64 -24
+// CHECK-LL-NEXT: %56 = bitcast i8* %vbase.offset.ptr95 to i64*
+// CHECK-LL-NEXT: %vbase.offset96 = load i64* %56
+// CHECK-LL-NEXT: %add.ptr97 = getelementptr i8* getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0), i64 %vbase.offset96
+// CHECK-LL-NEXT: %57 = bitcast i8* %add.ptr97 to %class.test1_A*
+// CHECK-LL-NEXT: br label %cast.end99
+// CHECK-LL: cast.null98:
+// CHECK-LL-NEXT: br label %cast.end99
+// CHECK-LL: cast.end99:
+// CHECK-LL-NEXT: %58 = phi %class.test1_A* [ %57, %cast.notnull93 ], [ null, %cast.null98 ]
+// CHECK-LL-NEXT: store %class.test1_A* %58, %class.test1_A** %ap
+// CHECK-LL-NEXT: %tmp100 = load %class.test1_A** %ap
+// CHECK-LL-NEXT: br i1 false, label %cast.null106, label %cast.notnull101
+// CHECK-LL: cast.notnull101:
+// CHECK-LL-NEXT: %vtable102 = load i8** bitcast (%class.test1_D* @test1_d to i8**)
+// CHECK-LL-NEXT: %vbase.offset.ptr103 = getelementptr i8* %vtable102, i64 -24
+// CHECK-LL-NEXT: %59 = bitcast i8* %vbase.offset.ptr103 to i64*
+// CHECK-LL-NEXT: %vbase.offset104 = load i64* %59
+// CHECK-LL-NEXT: %add.ptr105 = getelementptr i8* getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0), i64 %vbase.offset104
+// CHECK-LL-NEXT: %60 = bitcast i8* %add.ptr105 to %class.test1_A*
+// CHECK-LL-NEXT: br label %cast.end107
+// CHECK-LL: cast.null106:
+// CHECK-LL-NEXT: br label %cast.end107
+// CHECK-LL: cast.end107:
+// CHECK-LL-NEXT: %61 = phi %class.test1_A* [ %60, %cast.notnull101 ], [ null, %cast.null106 ]
+// CHECK-LL-NEXT: %cmp108 = icmp eq %class.test1_A* %tmp100, %61
+// CHECK-LL-NEXT: br i1 %cmp108, label %if.then109, label %if.else111
+// CHECK-LL: if.then109:
+// CHECK-LL-NEXT: %call110 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 12)
+// CHECK-LL-NEXT: br label %if.end113
+// CHECK-LL: if.else111:
+// CHECK-LL-NEXT: %call112 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 12)
+// CHECK-LL-NEXT: br label %if.end113
+// CHECK-LL: if.end113:
+// CHECK-LL-NEXT: br i1 false, label %cast.null116, label %cast.notnull115
+// CHECK-LL: cast.notnull115:
+// CHECK-LL-NEXT: br label %cast.end117
+// CHECK-LL: cast.null116:
+// CHECK-LL-NEXT: br label %cast.end117
+// CHECK-LL: cast.end117:
+// CHECK-LL-NEXT: %62 = phi %class.test1_E* [ bitcast (%class.test1_F* @test1_f to %class.test1_E*), %cast.notnull115 ], [ null, %cast.null116 ]
+// CHECK-LL-NEXT: store %class.test1_E* %62, %class.test1_E** %ep
+// CHECK-LL-NEXT: %tmp118 = load %class.test1_E** %ep
+// CHECK-LL-NEXT: br i1 false, label %cast.null120, label %cast.notnull119
+// CHECK-LL: cast.notnull119:
+// CHECK-LL-NEXT: br label %cast.end121
+// CHECK-LL: cast.null120:
+// CHECK-LL-NEXT: br label %cast.end121
+// CHECK-LL: cast.end121:
+// CHECK-LL-NEXT: %63 = phi %class.test1_E* [ bitcast (%class.test1_F* @test1_f to %class.test1_E*), %cast.notnull119 ], [ null, %cast.null120 ]
+// CHECK-LL-NEXT: %cmp122 = icmp eq %class.test1_E* %tmp118, %63
+// CHECK-LL-NEXT: br i1 %cmp122, label %if.then123, label %if.else125
+// CHECK-LL: if.then123:
+// CHECK-LL-NEXT: %call124 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 13)
+// CHECK-LL-NEXT: br label %if.end127
+// CHECK-LL: if.else125:
+// CHECK-LL-NEXT: %call126 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 13)
+// CHECK-LL-NEXT: br label %if.end127
+// CHECK-LL: if.end127:
+// CHECK-LL-NEXT: %tmp129 = load %class.test1_A** %ap
+// CHECK-LL-NEXT: %64 = icmp ne %class.test1_A* %tmp129, null
+// CHECK-LL-NEXT: br i1 %64, label %65, label %70
+// CHECK-LL: ; <label>:65
+// CHECK-LL-NEXT: %66 = bitcast %class.test1_A* %tmp129 to i64**
+// CHECK-LL-NEXT: %vtable130 = load i64** %66
+// CHECK-LL-NEXT: %67 = getelementptr inbounds i64* %vtable130, i64 -2
+// CHECK-LL-NEXT: %"offset to top" = load i64* %67
+// CHECK-LL-NEXT: %68 = bitcast %class.test1_A* %tmp129 to i8*
+// CHECK-LL-NEXT: %69 = getelementptr inbounds i8* %68, i64 %"offset to top"
+// CHECK-LL-NEXT: br label %71
+// CHECK-LL: ; <label>:70
+// CHECK-LL-NEXT: br label %71
+// CHECK-LL: ; <label>:71
+// CHECK-LL-NEXT: %72 = phi i8* [ %69, %65 ], [ null, %70 ]
+// CHECK-LL-NEXT: store i8* %72, i8** %vp
+// CHECK-LL-NEXT: %tmp131 = load i8** %vp
+// CHECK-LL-NEXT: %cmp132 = icmp eq i8* %tmp131, getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0)
+// CHECK-LL-NEXT: br i1 %cmp132, label %if.then133, label %if.else135
+// CHECK-LL: if.then133:
+// CHECK-LL-NEXT: %call134 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 14)
+// CHECK-LL-NEXT: br label %if.end137
+// CHECK-LL: if.else135:
+// CHECK-LL-NEXT: %call136 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 14)
+// CHECK-LL-NEXT: br label %if.end137
+// CHECK-LL: if.end137:
+// CHECK-LL-NEXT: %tmp139 = load %class.test1_A** %ap
+// CHECK-LL-NEXT: %73 = icmp ne %class.test1_A* %tmp139, null
+// CHECK-LL-NEXT: br i1 %73, label %74, label %79
+// CHECK-LL: ; <label>:74
+// CHECK-LL-NEXT: %75 = bitcast %class.test1_A* %tmp139 to i64**
+// CHECK-LL-NEXT: %vtable140 = load i64** %75
+// CHECK-LL-NEXT: %76 = getelementptr inbounds i64* %vtable140, i64 -2
+// CHECK-LL-NEXT: %"offset to top141" = load i64* %76
+// CHECK-LL-NEXT: %77 = bitcast %class.test1_A* %tmp139 to i8*
+// CHECK-LL-NEXT: %78 = getelementptr inbounds i8* %77, i64 %"offset to top141"
+// CHECK-LL-NEXT: br label %80
+// CHECK-LL: ; <label>:79
+// CHECK-LL-NEXT: br label %80
+// CHECK-LL: ; <label>:80
+// CHECK-LL-NEXT: %81 = phi i8* [ %78, %74 ], [ null, %79 ]
+// CHECK-LL-NEXT: store i8* %81, i8** %cvp
+// CHECK-LL-NEXT: %tmp142 = load i8** %cvp
+// CHECK-LL-NEXT: %cmp143 = icmp eq i8* %tmp142, getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0)
+// CHECK-LL-NEXT: br i1 %cmp143, label %if.then144, label %if.else146
+// CHECK-LL: if.then144:
+// CHECK-LL-NEXT: %call145 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 15)
+// CHECK-LL-NEXT: br label %if.end148
+// CHECK-LL: if.else146:
+// CHECK-LL-NEXT: %call147 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 15)
+// CHECK-LL-NEXT: br label %if.end148
+// CHECK-LL: if.end148:
+// CHECK-LL-NEXT: ret void
diff --git a/test/CodeGenCXX/empty-union.cpp b/test/CodeGenCXX/empty-union.cpp
new file mode 100644
index 000000000000..fdd97415a203
--- /dev/null
+++ b/test/CodeGenCXX/empty-union.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -emit-llvm -o - %s
+
+union sigval { };
+
+union sigval sigev_value;
+
+int main()
+{
+ return sizeof(sigev_value);
+}
diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp
index 8a9e65c4e2e3..b33ba85cf660 100644
--- a/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/test/CodeGenCXX/explicit-instantiation.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -triple i686-pc-linue-gnu -o %t %s &&
+// RUN: clang-cc -emit-llvm -triple i686-pc-linux-gnu -o %t %s
// RUN: grep "define i32 @_ZNK4plusIillEclERKiRKl" %t | count 1
template<typename T, typename U, typename Result>
diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp
index 635329323354..3af8f3adb54f 100644
--- a/test/CodeGenCXX/extern-c.cpp
+++ b/test/CodeGenCXX/extern-c.cpp
@@ -1,10 +1,10 @@
-// RUN: clang-cc -emit-llvm %s -o %t &&
+// RUN: clang-cc -emit-llvm %s -o %t
namespace foo {
-// RUN: not grep "@a = global i32" %t &&
+// RUN: not grep "@a = global i32" %t
extern "C" int a;
-// RUN: not grep "@_ZN3foo1bE = global i32" %t &&
+// RUN: not grep "@_ZN3foo1bE = global i32" %t
extern int b;
// RUN: grep "@_ZN3foo1cE = global i32" %t | count 1
diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp
new file mode 100644
index 000000000000..ebea9c156e27
--- /dev/null
+++ b/test/CodeGenCXX/global-array-destruction.cpp
@@ -0,0 +1,33 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+
+extern "C" int printf(...);
+
+int count;
+
+struct S {
+ S() : iS(++count) { printf("S::S(%d)\n", iS); }
+ ~S() { printf("S::~S(%d)\n", iS); }
+ int iS;
+};
+
+
+S arr[2][1];
+S s1;
+S arr1[3];
+static S sarr[4];
+
+int main () {}
+S arr2[2];
+static S sarr1[4];
+S s2;
+S arr3[3];
+
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
+// CHECK-LP64: call ___cxa_atexit
diff --git a/test/CodeGenCXX/implicit-instantiation-1.cpp b/test/CodeGenCXX/implicit-instantiation-1.cpp
index f6c6114d20c3..cc86ef4cb502 100644
--- a/test/CodeGenCXX/implicit-instantiation-1.cpp
+++ b/test/CodeGenCXX/implicit-instantiation-1.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm %s -o %t &&
+// RUN: clang-cc -emit-llvm %s -o %t
template<typename T>
struct X {
@@ -11,18 +11,17 @@ struct X {
};
void foo(X<int> &xi, X<float> *xfp, int i, float f) {
- // RUN: grep "linkonce_odr.*_ZN1XIiE1fEi" %t | count 1 &&
+ // RUN: grep "linkonce_odr.*_ZN1XIiE1fEi" %t | count 1
xi.f(i);
- // RUN: grep "linkonce_odr.*_ZN1XIiE1gEi" %t | count 1 &&
+ // RUN: grep "linkonce_odr.*_ZN1XIiE1gEi" %t | count 1
xi.g(f);
- // RUN: grep "linkonce_odr.*_ZN1XIfE1fEf" %t | count 1 &&
+ // RUN: grep "linkonce_odr.*_ZN1XIfE1fEf" %t | count 1
xfp->f(f);
- // RUN: grep "linkonce_odr.*_ZN1XIfE1hEf" %t | count 0 &&
+ // RUN: grep "linkonce_odr.*_ZN1XIfE1hEf" %t | count 0
- // RUN: true
}
diff --git a/test/CodeGenCXX/init-incomplete-type.cpp b/test/CodeGenCXX/init-incomplete-type.cpp
new file mode 100644
index 000000000000..402b86ea8cb4
--- /dev/null
+++ b/test/CodeGenCXX/init-incomplete-type.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc %s -emit-llvm-only -verify
+// PR5489
+
+template<typename E>
+struct Bar {
+ int x_;
+};
+
+static struct Bar<int> bar[1] = {
+ { 0 }
+};
+
diff --git a/test/CodeGenCXX/instantiate-init-list.cpp b/test/CodeGenCXX/instantiate-init-list.cpp
new file mode 100644
index 000000000000..7d5458af1f55
--- /dev/null
+++ b/test/CodeGenCXX/instantiate-init-list.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc %s -emit-llvm-only -verify
+
+struct F {
+ void (*x)();
+};
+void G();
+template<class T> class A {
+ A();
+};
+template<class T> A<T>::A() {
+ static F f = { G };
+}
+A<int> a;
diff --git a/test/CodeGenCXX/mangle-subst.cpp b/test/CodeGenCXX/mangle-subst.cpp
index 46a21b62b515..a940f4f447b6 100644
--- a/test/CodeGenCXX/mangle-subst.cpp
+++ b/test/CodeGenCXX/mangle-subst.cpp
@@ -59,3 +59,11 @@ template void ft3<int>(S1<int>, S1<char>);
// CHECK: @_Z1fPKcS0_
void f(const char*, const char*) {}
+namespace NS {
+ class C;
+}
+
+namespace NS {
+ // CHECK: @_ZN2NS1fERNS_1CE
+ void f(C&) { }
+}
diff --git a/test/CodeGenCXX/mangle-system-header.cpp b/test/CodeGenCXX/mangle-system-header.cpp
new file mode 100644
index 000000000000..8c642bd07533
--- /dev/null
+++ b/test/CodeGenCXX/mangle-system-header.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
+
+// PR5420
+
+# 1 "fake_system_header.h" 1 3 4
+// CHECK: define void @_ZdlPvS_(
+void operator delete (void*, void*) {}
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index 2ffbae71da01..03e405ecba1d 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -221,3 +221,9 @@ struct S7 {
// CHECK: @"_ZN2S73$_0C1Ev"
S7::S7() {}
+// PR5063
+template<typename T> typename __enable_if<(__is_scalar<T>::__value), void>::__type ft8() { }
+// CHECK: @_Z3ft8IiEN11__enable_ifIXsr11__is_scalarIT_E7__valueEvE6__typeEv
+template void ft8<int>();
+// CHECK: @_Z3ft8IPvEN11__enable_ifIXsr11__is_scalarIT_E7__valueEvE6__typeEv
+template void ft8<void*>();
diff --git a/test/CodeGenCXX/member-expressions.cpp b/test/CodeGenCXX/member-expressions.cpp
new file mode 100644
index 000000000000..f90b80733905
--- /dev/null
+++ b/test/CodeGenCXX/member-expressions.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s
+
+// PR5392
+namespace PR5392 {
+struct A
+{
+ static int a;
+};
+
+A a1;
+void f()
+{
+ // CHECK: store i32 10, i32* @_ZN6PR53921A1aE
+ a1.a = 10;
+ // CHECK: store i32 20, i32* @_ZN6PR53921A1aE
+ A().a = 20;
+}
+
+}
diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp
index a7c21133d051..7792560e067b 100644
--- a/test/CodeGenCXX/member-function-pointers.cpp
+++ b/test/CodeGenCXX/member-function-pointers.cpp
@@ -30,8 +30,8 @@ void f() {
// CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 1)
vpa = 0;
- // CHECK: store i64 %0, i64* getelementptr inbounds (%0* @pc, i32 0, i32 0)
- // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 %1, 16
+ // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pc, i32 0, i32 0)
+ // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 16
// CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pc, i32 0, i32 1)
pc = pa;
}
@@ -46,7 +46,7 @@ void f2() {
// CHECK: [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0
// CHECK: store i64 1, i64* [[pa3ptr]]
// CHECK: [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1
- // CHECK: store i64 0, i64* [[pa2adj]]
+ // CHECK: store i64 0, i64* [[pa3adj]]
void (A::*pa3)() = &A::vf;
}
diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp
index 29629d5bf824..0dfaedff931c 100644
--- a/test/CodeGenCXX/member-functions.cpp
+++ b/test/CodeGenCXX/member-functions.cpp
@@ -1,43 +1,43 @@
-// RUN: clang-cc -emit-llvm %s -triple x86_64-apple-darwin9 -o %t &&
+// RUN: clang-cc -emit-llvm %s -triple x86_64-apple-darwin9 -o %t
struct C {
void f();
void g(int, ...);
};
-// RUN: grep "define void @_ZN1C1fEv" %t | count 1 &&
+// RUN: grep "define void @_ZN1C1fEv" %t | count 1
void C::f() {
}
void test1() {
C c;
-// RUN: grep "call void @_ZN1C1fEv" %t | count 1 &&
+// RUN: grep "call void @_ZN1C1fEv" %t | count 1
c.f();
-// RUN: grep "call void (.struct.C\*, i32, ...)\* @_ZN1C1gEiz" %t | count 1 &&
+// RUN: grep "call void (.struct.C\*, i32, ...)\* @_ZN1C1gEiz" %t | count 1
c.g(1, 2, 3);
}
struct S {
- // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t &&
+ // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t
inline S() { }
- // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t &&
+ // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t
inline ~S() { }
- // RUN: grep "define linkonce_odr void @_ZN1S9f_inline1Ev" %t &&
+ // RUN: grep "define linkonce_odr void @_ZN1S9f_inline1Ev" %t
void f_inline1() { }
- // RUN: grep "define linkonce_odr void @_ZN1S9f_inline2Ev" %t &&
+ // RUN: grep "define linkonce_odr void @_ZN1S9f_inline2Ev" %t
inline void f_inline2() { }
- // RUN: grep "define linkonce_odr void @_ZN1S1gEv" %t &&
+ // RUN: grep "define linkonce_odr void @_ZN1S1gEv" %t
static void g() { }
static void f();
};
-// RUN: grep "define void @_ZN1S1fEv" %t &&
+// RUN: grep "define void @_ZN1S1fEv" %t
void S::f() {
}
diff --git a/test/CodeGenCXX/member-init-struct.cpp b/test/CodeGenCXX/member-init-struct.cpp
new file mode 100644
index 000000000000..9c0c3919794e
--- /dev/null
+++ b/test/CodeGenCXX/member-init-struct.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-cc %s -emit-llvm-only -verify
+
+struct A {int a;};
+struct B {float a;};
+struct C {
+ union {
+ A a;
+ B b[10];
+ };
+ _Complex float c;
+ int d[10];
+ void (C::*e)();
+ C() : a(), c(), d(), e() {}
+ C(A x) : a(x) {}
+ C(void (C::*x)(), int y) : b(), c(y), e(x) {}
+};
+A x;
+C a, b(x), c(0, 2);
diff --git a/test/CodeGenCXX/member-init-union.cpp b/test/CodeGenCXX/member-init-union.cpp
new file mode 100644
index 000000000000..334d5fd1f1c4
--- /dev/null
+++ b/test/CodeGenCXX/member-init-union.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc %s -emit-llvm-only -verify
+
+union x {
+ int a;
+ float b;
+ x(float y) : b(y) {}
+ x(int y) : a(y) {}
+};
+x a(1), b(1.0f);
+
diff --git a/test/CodeGenCXX/member-pointers-zero-init.cpp b/test/CodeGenCXX/member-pointers-zero-init.cpp
index e7b0fdafba6a..caf31bd0621a 100644
--- a/test/CodeGenCXX/member-pointers-zero-init.cpp
+++ b/test/CodeGenCXX/member-pointers-zero-init.cpp
@@ -1,30 +1,30 @@
-// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 &&
+// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9
struct A {
int i;
};
-// RUN: grep "@a = global i64 -1" %t &&
+// RUN: grep "@a = global i64 -1" %t
int A::* a;
-// RUN: grep "@aa = global \[2 x i64\] \[i64 -1, i64 -1\]" %t &&
+// RUN: grep "@aa = global \[2 x i64\] \[i64 -1, i64 -1\]" %t
int A::* aa[2];
-// RUN: grep "@aaa = global \[2 x \[2 x i64\]\] \[\[2 x i64\] \[i64 -1, i64 -1\], \[2 x i64\] \[i64 -1, i64 -1\]\]" %t &&
+// RUN: grep "@aaa = global \[2 x \[2 x i64\]\] \[\[2 x i64\] \[i64 -1, i64 -1\], \[2 x i64\] \[i64 -1, i64 -1\]\]" %t
int A::* aaa[2][2];
-// RUN: grep "@b = global i64 -1" %t &&
+// RUN: grep "@b = global i64 -1" %t
int A::* b = 0;
void f() {
- // RUN: grep "%.* = icmp ne i64 %.*, -1" %t | count 2 &&
+ // RUN: grep "%.* = icmp ne i64 %.*, -1" %t | count 2
if (a) { }
if (a != 0) { }
- // RUN: grep "%.* = icmp ne i64 -1, %.*" %t | count 1 &&
+ // RUN: grep "%.* = icmp ne i64 -1, %.*" %t | count 1
if (0 != a) { }
- // RUN: grep "%.* = icmp eq i64 %.*, -1" %t | count 1 &&
+ // RUN: grep "%.* = icmp eq i64 %.*, -1" %t | count 1
if (a == 0) { }
// RUN: grep "%.* = icmp eq i64 -1, %.*" %t | count 1
diff --git a/test/CodeGenCXX/new-operator-phi.cpp b/test/CodeGenCXX/new-operator-phi.cpp
new file mode 100644
index 000000000000..a5eed28ccf95
--- /dev/null
+++ b/test/CodeGenCXX/new-operator-phi.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-cc -emit-llvm-only -verify %s
+// PR5454
+#include <stddef.h>
+
+class X {static void * operator new(size_t size) throw(); X(int); };
+int a(), b();
+void b(int x)
+{
+ new X(x ? a() : b());
+}
+
diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp
index c6cee1845670..3f191de23bcf 100644
--- a/test/CodeGenCXX/new.cpp
+++ b/test/CodeGenCXX/new.cpp
@@ -1,11 +1,12 @@
// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
+#include <stddef.h>
void t1() {
int* a = new int;
}
// Placement.
-void* operator new(unsigned long, void*) throw();
+void* operator new(size_t, void*) throw();
void t2(int* a) {
int* b = new (a) int;
diff --git a/test/CodeGenCXX/ptr-to-member-function.cpp b/test/CodeGenCXX/ptr-to-member-function.cpp
index 15019081c062..52190b937377 100644
--- a/test/CodeGenCXX/ptr-to-member-function.cpp
+++ b/test/CodeGenCXX/ptr-to-member-function.cpp
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
// 13.3.3.2 Ranking implicit conversion sequences
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/reinterpret-cast.cpp b/test/CodeGenCXX/reinterpret-cast.cpp
index ae3ab2f8b0d7..58a980d5288c 100644
--- a/test/CodeGenCXX/reinterpret-cast.cpp
+++ b/test/CodeGenCXX/reinterpret-cast.cpp
@@ -9,4 +9,9 @@ unsigned long f2() {
unsigned long f3(void *p) {
return reinterpret_cast<unsigned long>(p);
+}
+
+void f4(int*&);
+void f5(void*& u) {
+ f4(reinterpret_cast<int*&>(u));
} \ No newline at end of file
diff --git a/test/CodeGenCXX/rtti.cpp b/test/CodeGenCXX/rtti.cpp
new file mode 100644
index 000000000000..a1ff1ff68729
--- /dev/null
+++ b/test/CodeGenCXX/rtti.cpp
@@ -0,0 +1,207 @@
+// RUN: clang-cc -I%S -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t.s
+// RUN: FileCheck --input-file=%t.s %s
+
+// RUN: clang-cc -I%S -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t.ll
+// RUN: FileCheck -check-prefix LL --input-file=%t.ll %s
+
+#include <typeinfo>
+
+class test1_B1 {
+ virtual void foo() { }
+};
+class test1_B2 : public test1_B1 {
+ virtual void foo() { }
+};
+class test1_B3 : public test1_B2, public test1_B1 {
+ virtual void foo() { }
+};
+class test1_B4 : virtual public test1_B3 {
+ virtual void foo() { }
+};
+class test1_B5 : virtual test1_B3, test1_B4 {
+ virtual void foo() { }
+};
+class test1_B6 {
+ virtual void foo() { }
+};
+class test1_B7 : public test1_B6, public test1_B5 {
+ virtual void foo() { }
+};
+class test1_D : public test1_B7 {
+ virtual void foo() { }
+} d1;
+
+// CHECK: __ZTSPVi:
+// CHECK-NEXT: .asciz "PVi"
+
+// CHECK: __ZTIPVi:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv119__pointer_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTSPVi
+// CHECK-NEXT: .long 2
+// CHECK-NEXT: .space 4
+// CHECK-NEXT: .quad __ZTIi
+
+// CHECK: .globl __ZTS7test3_A
+// CHECK-NEXT: .weak_definition __ZTS7test3_A
+// CHECK: __ZTS7test3_A:
+// CHECK-NEXT: .asciz "7test3_A"
+
+// CHECK: __ZTIM7test3_Ai:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv129__pointer_to_member_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTSM7test3_Ai
+// CHECK-NEXT: .space 4
+// CHECK-NEXT: .space 4
+// CHECK-NEXT: .quad __ZTIi
+// CHECK-NEXT: .quad __ZTI7test3_A
+
+// CHECK: __ZTIM7test3_Ii:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv129__pointer_to_member_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTSM7test3_Ii
+// CHECK-NEXT: .long 16
+// CHECK-NEXT: .space 4
+// CHECK-NEXT: .quad __ZTIi
+// CHECK-NEXT: .quad __ZTI7test3_I
+
+// CHECK: .private_extern __ZTIFvvE
+// CHECK: .globl __ZTIFvvE
+// CHECK: .weak_definition __ZTIFvvE
+// CHECK: __ZTIFvvE:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv120__function_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTSFvvE
+
+// CHECK: __ZTIM7test3_AFvvE:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv129__pointer_to_member_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTSM7test3_AFvvE
+// CHECK-NEXT: .space 4
+// CHECK-NEXT: .space 4
+// CHECK-NEXT: .quad __ZTIFvvE
+// CHECK-NEXT: .quad __ZTI7test3_A
+
+
+
+// CHECK:__ZTI7test1_D:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv120__si_class_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTS7test1_D
+// CHECK-NEXT: .quad __ZTI8test1_B7
+
+// CHECK:__ZTI8test1_B7:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTS8test1_B7
+// CHECK-NEXT: .long 3
+// CHECK-NEXT: .long 2
+// CHECK-NEXT: .quad __ZTI8test1_B6
+// CHECK-NEXT: .quad 2
+// CHECK-NEXT: .quad __ZTI8test1_B5
+// CHECK-NEXT: .quad 2050
+
+// CHECK:__ZTI8test1_B5:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTS8test1_B5
+// CHECK-NEXT: .long 3
+// CHECK-NEXT: .long 2
+// CHECK-NEXT: .quad __ZTI8test1_B3
+// CHECK-NEXT: .quad 18446744073709545473
+// CHECK-NEXT: .quad __ZTI8test1_B4
+// CHECK-NEXT: .space 8
+
+// CHECK:__ZTI8test1_B4:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTS8test1_B4
+// CHECK-NEXT: .long 1
+// CHECK-NEXT: .long 1
+// CHECK-NEXT: .quad __ZTI8test1_B3
+// CHECK-NEXT: .quad 18446744073709545475
+
+// CHECK:__ZTI8test1_B6:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv117__class_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTS8test1_B6
+
+// CHECK:__ZTI8test1_B3:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTS8test1_B3
+// CHECK-NEXT: .long 1
+// CHECK-NEXT: .long 2
+// CHECK-NEXT: .quad __ZTI8test1_B2
+// CHECK-NEXT: .quad 2
+// CHECK-NEXT: .quad __ZTI8test1_B1
+// CHECK-NEXT: .quad 2050
+
+// CHECK:__ZTS8test1_B1:
+// CHECK-NEXT: .asciz "8test1_B1"
+
+// CHECK:__ZTI8test1_B1:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv117__class_type_infoE) + 16
+// CHECK-NEXT:. quad __ZTS8test1_B1
+
+// CHECK:__ZTS8test1_B2:
+// CHECK-NEXT: .asciz "8test1_B2"
+
+// CHECK:__ZTI8test1_B2:
+// CHECK-NEXT: .quad (__ZTVN10__cxxabiv120__si_class_type_infoE) + 16
+// CHECK-NEXT: .quad __ZTS8test1_B2
+// CHECK-NEXT: .quad __ZTI8test1_B1
+
+
+class NP { };
+void test2_1();
+void test2_2(test1_D *dp) {
+ test1_D &d = *dp;
+ if (typeid(d) == typeid(test1_D))
+ test2_1();
+ if (typeid(NP) == typeid(test1_D))
+ test2_1();
+ if (typeid(((*(dp)))) == typeid(test1_D))
+ test2_1();
+ if (typeid(int) == typeid(float))
+ test2_1();
+ if (typeid(int*) == typeid(const int *))
+ test2_1();
+}
+
+// CHECK-LL:define void @_Z7test2_2P7test1_D(%class.test1_B7* %dp) nounwind {
+// CHECK-LL: %tmp1 = load %class.test1_B7** %d
+// CHECK-LL-NEXT: %0 = bitcast %class.test1_B7* %tmp1 to %"class.std::type_info"***
+// CHECK-LL-NEXT: %vtable = load %"class.std::type_info"*** %0
+// CHECK-LL-NEXT: %1 = getelementptr inbounds %"class.std::type_info"** %vtable, i64 -1
+// CHECK-LL-NEXT: %2 = load %"class.std::type_info"** %1
+// CHECK-LL-NEXT: %call = call zeroext i1 @_ZNKSt9type_infoeqERKS_(%"class.std::type_info"* %2, %"class.std::type_info"* bitcast (%{{[0-9]*}}* @_ZTI7test1_D to %"class.std::type_info"*))
+
+// CHECK-LL: %call2 = call zeroext i1 @_ZNKSt9type_infoeqERKS_(%"class.std::type_info"* bitcast (%0* @_ZTI2NP to %"class.std::type_info"*), %"class.std::type_info"* bitcast (%{{[0-9]*}}* @_ZTI7test1_D to %"class.std::type_info"*))
+
+// CHECK-LL: %3 = bitcast %class.test1_B7* %tmp5 to %"class.std::type_info"***
+// CHECK-LL-NEXT: %4 = icmp ne %"class.std::type_info"*** %3, null
+// CHECK-LL-NEXT: br i1 %4, label %6, label %5
+// CHECK-LL: ; <label>:5
+// CHECK-LL-NEXT: call void @__cxa_bad_typeid()
+// CHECK-LL-NEXT: unreachable
+// CHECK-LL: ; <label>:6
+// CHECK-LL-NEXT: %vtable6 = load %"class.std::type_info"*** %3
+// CHECK-LL-NEXT: %7 = getelementptr inbounds %"class.std::type_info"** %vtable6, i64 -1
+// CHECK-LL-NEXT: %8 = load %"class.std::type_info"** %7
+// CHECK-LL-NEXT: %call7 = call zeroext i1 @_ZNKSt9type_infoeqERKS_(%"class.std::type_info"* %8, %"class.std::type_info"* bitcast (%{{[0-9]*}}* @_ZTI7test1_D to %"class.std::type_info"*))
+
+// CHECK-LL: %call10 = call zeroext i1 @_ZNKSt9type_infoeqERKS_(%"class.std::type_info"* bitcast (i8** @_ZTIi to %"class.std::type_info"*), %"class.std::type_info"* bitcast (i8** @_ZTIf to %"class.std::type_info"*))
+
+// CHECK-LL: %call13 = call zeroext i1 @_ZNKSt9type_infoeqERKS_(%"class.std::type_info"* bitcast (i8** @_ZTIPi to %"class.std::type_info"*), %"class.std::type_info"* bitcast (i8** @_ZTIPKi to %"class.std::type_info"*))
+
+class test3_A { };
+class test3_I;
+int (test3_A::*pmd);
+int (test3_I::*i_pmd);
+void (test3_A::*pmf)();
+int test3() {
+ if (typeid(volatile int *) == typeid(int *))
+ return 1;
+ if (typeid(pmd) == typeid(i_pmd))
+ return 1;
+ if (typeid(pmd) == typeid(pmf))
+ return 1;
+ return 0;
+ enum a { };
+ if (typeid(int[5]) == typeid(enum a))
+ return 0;
+}
+
+bool test4(std::type_info* __pointee) {
+ return *__pointee == typeid (void);
+}
diff --git a/test/CodeGenCXX/static-init-1.cpp b/test/CodeGenCXX/static-init-1.cpp
new file mode 100644
index 000000000000..2c452022c525
--- /dev/null
+++ b/test/CodeGenCXX/static-init-1.cpp
@@ -0,0 +1,23 @@
+// RUN: clang-cc -triple=x86_64-apple-darwin9 -emit-llvm %s -o %t
+// RUN: grep "call i32 @_Z5func1i" %t | count 3
+
+extern "C" int printf(...);
+
+static int count;
+
+int func2(int c) { return printf("loading the func2(%d)\n", c); };
+int func1(int c) { return printf("loading the func1(%d)\n", c); }
+
+static int loader_1 = func1(++count);
+
+int loader_2 = func2(++count);
+
+static int loader_3 = func1(++count);
+
+
+int main() {}
+
+int loader_4 = func2(++count);
+static int loader_5 = func1(++count);
+int loader_6 = func2(++count);
+
diff --git a/test/CodeGenCXX/static-init-2.cpp b/test/CodeGenCXX/static-init-2.cpp
new file mode 100644
index 000000000000..e229dd4aa734
--- /dev/null
+++ b/test/CodeGenCXX/static-init-2.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-cc -emit-llvm-only -verify %s
+
+// Make sure we don't crash generating y; its value is constant, but the
+// initializer has side effects, so EmitConstantExpr should fail.
+int x();
+int y = x() && 0;
diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp
index 44dd14284107..55877b2a71a9 100644
--- a/test/CodeGenCXX/static-init.cpp
+++ b/test/CodeGenCXX/static-init.cpp
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple=x86_64-apple-darwin9 -emit-llvm %s -o %t &&
-// RUN: grep "call void @_ZN1AC1Ev" %t | count 1 &&
+// RUN: clang-cc -triple=x86_64-apple-darwin9 -emit-llvm %s -o %t
+// RUN: grep "call void @_ZN1AC1Ev" %t | count 1
// RUN: grep "call i32 @__cxa_atexit(void (i8\*)\* bitcast (void (%.truct.A\*)\* @_ZN1AD1Ev to void (i8\*)\*), i8\* getelementptr inbounds (%.truct.A\* @_ZZ1fvE1a, i32 0, i32 0), i8\* bitcast (i8\*\* @__dso_handle to i8\*))" %t | count 1
struct A {
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index e9ed0f7690bc..e55027460f0c 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -115,3 +115,90 @@ void f7() {
// CHECK: call void @_ZN1GD1Ev
a(G());
}
+
+namespace PR5077 {
+
+struct A {
+ A();
+ ~A();
+ int f();
+};
+
+void f();
+int g(const A&);
+
+struct B {
+ int a1;
+ int a2;
+ B();
+ ~B();
+};
+
+B::B()
+ // CHECK: call void @_ZN6PR50771AC1Ev
+ // CHECK: call i32 @_ZN6PR50771A1fEv
+ // CHECK: call void @_ZN6PR50771AD1Ev
+ : a1(A().f())
+ // CHECK: call void @_ZN6PR50771AC1Ev
+ // CHECK: call i32 @_ZN6PR50771gERKNS_1AE
+ // CHECK: call void @_ZN6PR50771AD1Ev
+ , a2(g(A()))
+{
+ // CHECK: call void @_ZN6PR50771fEv
+ f();
+}
+
+struct C {
+ C();
+
+ const B& b;
+};
+
+C::C()
+ // CHECK: call void @_ZN6PR50771BC1Ev
+ : b(B()) {
+ // CHECK: call void @_ZN6PR50771fEv
+ f();
+
+ // CHECK: call void @_ZN6PR50771BD1Ev
+}
+}
+
+A f8() {
+ // CHECK: call void @_ZN1AC1Ev
+ // CHECK-NOT: call void @_ZN1AD1Ev
+ return A();
+ // CHECK: ret void
+}
+
+struct H {
+ H();
+ ~H();
+ H(const H&);
+};
+
+void f9(H h) {
+ // CHECK: call void @_ZN1HC1Ev
+ // CHECK: call void @_Z2f91H
+ // CHECK: call void @_ZN1HD1Ev
+ f9(H());
+
+ // CHECK: call void @_ZN1HC1ERKS_
+ // CHECK: call void @_Z2f91H
+ // CHECK: call void @_ZN1HD1Ev
+ f9(h);
+}
+
+void f10(const H&);
+
+void f11(H h) {
+ // CHECK: call void @_ZN1HC1Ev
+ // CHECK: call void @_Z3f10RK1H
+ // CHECK: call void @_ZN1HD1Ev
+ f10(H());
+
+ // CHECK: call void @_Z3f10RK1H
+ // CHECK-NOT: call void @_ZN1HD1Ev
+ // CHECK: ret void
+ f10(h);
+} \ No newline at end of file
diff --git a/test/CodeGenCXX/trivial-constructor-init.cpp b/test/CodeGenCXX/trivial-constructor-init.cpp
index 183b31a801e3..90d6e655d8d8 100644
--- a/test/CodeGenCXX/trivial-constructor-init.cpp
+++ b/test/CodeGenCXX/trivial-constructor-init.cpp
@@ -1,6 +1,5 @@
-// RUN: clang-cc -S %s -o %t-64.s &&
-// RUN: clang-cc -S %s -o %t-32.s &&
-// RUN: true
+// RUN: clang-cc -S %s -o %t-64.s
+// RUN: clang-cc -S %s -o %t-32.s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/typeinfo b/test/CodeGenCXX/typeinfo
new file mode 100644
index 000000000000..7af23cf12f0d
--- /dev/null
+++ b/test/CodeGenCXX/typeinfo
@@ -0,0 +1,16 @@
+namespace std {
+ class type_info {
+ public:
+ virtual ~type_info();
+ const char* name() const { return __name; }
+ bool operator==(const type_info& __arg) const {
+ return __name == __arg.__name;
+ }
+
+ bool operator!=(const type_info& __arg) const {
+ return !operator==(__arg);
+ }
+ protected:
+ const char *__name;
+ };
+}
diff --git a/test/CodeGenCXX/vararg-conversion-ctor.cpp b/test/CodeGenCXX/vararg-conversion-ctor.cpp
new file mode 100644
index 000000000000..1306abf4a63d
--- /dev/null
+++ b/test/CodeGenCXX/vararg-conversion-ctor.cpp
@@ -0,0 +1,23 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t-64.ll
+// RUN: FileCheck -check-prefix LPLL64 --input-file=%t-64.ll %s
+
+extern "C" int printf(...);
+
+struct A {
+ A(...) {
+ printf("A::A(...)\n");
+ }
+};
+
+A a(1.34);
+
+A b = 2.34;
+
+int main()
+{
+ A c[3];
+}
+
+// CHECK-LPLL64: call void (%struct.A*, ...)
+// CHECK-LPLL64: call void (%struct.A*, ...)
+// CHECK-LPLL64: call void (%struct.A*, ...)
diff --git a/test/CodeGenCXX/virt-dtor-gen.cpp b/test/CodeGenCXX/virt-dtor-gen.cpp
new file mode 100644
index 000000000000..704d735c776e
--- /dev/null
+++ b/test/CodeGenCXX/virt-dtor-gen.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -o - -emit-llvm %s | FileCheck %s
+// PR5483
+
+// Make sure we generate all three forms of the destructor when it is virtual.
+class Foo {
+ virtual ~Foo();
+};
+Foo::~Foo() {}
+
+// CHECK: define void @_ZN3FooD0Ev
diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp
index 193a96ddd589..b453ed55df3e 100644
--- a/test/CodeGenCXX/virt.cpp
+++ b/test/CodeGenCXX/virt.cpp
@@ -1,14 +1,8 @@
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -O0 -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 -input-file=%t-32.s %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
-// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O3 -S %s -o %t-O3-64.s &&
-// RUN: FileCheck -check-prefix LPOPT64 --input-file=%t-O3-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -O3 -S %s -o %t-O3-32.s &&
-// RUN: FileCheck -check-prefix LPOPT32 -input-file=%t-O3-32.s %s &&
-
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t-64.ll
+// RUN: FileCheck -check-prefix LPLL64 --input-file=%t-64.ll %s
struct B {
virtual void bar1();
@@ -56,8 +50,8 @@ void test2() {
j = sz;
// FIXME: These should result in a frontend constant a la fold, no run time
// initializer
- // CHECK-LPOPT32: movl $4, __ZZ5test2vE2sz
- // CHECK-LPOPT64: movl $8, __ZZ5test2vE2sz(%rip)
+ // 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");
@@ -85,10 +79,6 @@ int main() {
ap->b = 2;
}
-// CHECK-LP32: main:
-// CHECK-LP32: movl $1, 8(%eax)
-// CHECK-LP32: movl $2, 4(%eax)
-
// CHECK-LP64: main:
// CHECK-LP64: movl $1, 12(%rax)
// CHECK-LP64: movl $2, 8(%rax)
@@ -114,56 +104,14 @@ void test12_foo() {
test12_pa->test12_A::foo();
}
-// CHECK-LPOPT32:__Z10test12_foov:
-// CHECK-LPOPT32: movl _test12_pa, %eax
-// CHECK-LPOPT32-NEXT: movl (%eax), %ecx
-// CHECK-LPOPT32-NEXT: movl %eax, (%esp)
-// CHECK-LPOPT32-NEXT: call *(%ecx)
-// CHECK-LPOPT32-NEXT: movl _test12_pb, %eax
-// CHECK-LPOPT32-NEXT: movl (%eax), %ecx
-// CHECK-LPOPT32-NEXT: movl %eax, (%esp)
-// CHECK-LPOPT32-NEXT: call *(%ecx)
-// CHECK-LPOPT32-NEXT: movl _test12_pd, %eax
-// CHECK-LPOPT32-NEXT: movl (%eax), %ecx
-// CHECK-LPOPT32-NEXT: movl %eax, (%esp)
-// CHECK-LPOPT32-NEXT: call *(%ecx)
-// CHECK-LPOPT32-NEXT: movl _test12_pa, %eax
-// CHECK-LPOPT32-NEXT: movl (%eax), %ecx
-// CHECK-LPOPT32-NEXT: movl %eax, (%esp)
-// CHECK-LPOPT32-NEXT: call *4(%ecx)
-// CHECK-LPOPT32-NEXT: movl _test12_pb, %eax
-// CHECK-LPOPT32-NEXT: movl (%eax), %ecx
-// CHECK-LPOPT32-NEXT: movl %eax, (%esp)
-// CHECK-LPOPT32-NEXT: call *4(%ecx)
-// CHECK-LPOPT32-NEXT: movl _test12_pd, %eax
-// CHECK-LPOPT32-NEXT: movl (%eax), %ecx
-// CHECK-LPOPT32-NEXT: movl %eax, (%esp)
-// CHECK-LPOPT32-NEXT: call *4(%ecx)
-// CHECK-LPOPT32-NEXT: movl _test12_pa, %eax
-// CHECK-LPOPT32-NEXT: movl %eax, (%esp)
-// CHECK-LPOPT32-NEXT: call L__ZN8test12_A3fooEv$stub
-
-// CHECK-LPOPT64:__Z10test12_foov:
-// CHECK-LPOPT64: movq _test12_pa(%rip), %rdi
-// CHECK-LPOPT64-NEXT: movq (%rdi), %rax
-// CHECK-LPOPT64-NEXT: call *(%rax)
-// CHECK-LPOPT64-NEXT: movq _test12_pb(%rip), %rdi
-// CHECK-LPOPT64-NEXT: movq (%rdi), %rax
-// CHECK-LPOPT64-NEXT: call *(%rax)
-// CHECK-LPOPT64-NEXT: movq _test12_pd(%rip), %rdi
-// CHECK-LPOPT64-NEXT: movq (%rdi), %rax
-// CHECK-LPOPT64-NEXT: call *(%rax)
-// CHECK-LPOPT64-NEXT: movq _test12_pa(%rip), %rdi
-// CHECK-LPOPT64-NEXT: movq (%rdi), %rax
-// CHECK-LPOPT64-NEXT: call *8(%rax)
-// CHECK-LPOPT64-NEXT: movq _test12_pb(%rip), %rdi
-// CHECK-LPOPT64-NEXT: movq (%rdi), %rax
-// CHECK-LPOPT64-NEXT: call *8(%rax)
-// CHECK-LPOPT64-NEXT: movq _test12_pd(%rip), %rdi
-// CHECK-LPOPT64-NEXT: movq (%rdi), %rax
-// CHECK-LPOPT64-NEXT: call *8(%rax)
-// CHECK-LPOPT64-NEXT: movq _test12_pa(%rip), %rdi
-// CHECK-LPOPT64-NEXT: call __ZN8test12_A3fooEv
+// CHECK-LPLL64:define void @_Z10test12_foov() nounwind {
+// CHECK-LPLL64: call void %2(%class.test14* %tmp)
+// CHECK-LPLL64: call void %5(%class.test14* %tmp1)
+// CHECK-LPLL64: call void %8(%class.test14* %tmp3)
+// CHECK-LPLL64: call void %11(%class.test14* %tmp5)
+// CHECK-LPLL64: call void %14(%class.test14* %tmp7)
+// CHECK-LPLL64: call void %17(%class.test14* %tmp9)
+// CHECK-LPLL64: call void @_ZN8test12_A3fooEv(%class.test14* %tmp11)
struct test6_B2 { virtual void funcB2(); char b[1000]; };
@@ -172,7 +120,6 @@ struct test6_B1 : virtual test6_B2 { virtual void funcB1(); };
struct test6_D : test6_B2, virtual test6_B1 {
};
-// CHECK-LP32: .zerofill __DATA, __common, _d6, 2012, 4
// CHECK-LP64: .zerofill __DATA, __common, _d6, 2024, 4
struct test7_B2 { virtual void funcB2(); };
@@ -181,7 +128,6 @@ struct test7_B1 : virtual test7_B2 { virtual void funcB1(); };
struct test7_D : test7_B2, virtual test7_B1 {
};
-// CHECK-LP32: .zerofill __DATA, __common, _d7, 8, 3
// CHECK-LP64: .zerofill __DATA, __common, _d7, 16, 3
@@ -193,20 +139,6 @@ struct test3_D : virtual test3_B1 {
virtual void funcD() { }
};
-// CHECK-LP32:__ZTV7test3_D:
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI7test3_D
-// CHECK-LP32-NEXT: .long __ZN8test3_B36funcB3Ev
-// CHECK-LP32-NEXT: .long __ZN8test3_B26funcB2Ev
-// CHECK-LP32-NEXT: .long __ZN8test3_B16funcB1Ev
-// CHECK-LP32-NEXT: .long __ZN7test3_D5funcDEv
-
// CHECK-LP64:__ZTV7test3_D:
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
@@ -224,22 +156,6 @@ struct test3_D : virtual test3_B1 {
struct test4_D : virtual B, virtual C {
};
-// CHECK-LP32:__ZTV7test4_D:
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI7test4_D
-// CHECK-LP32-NEXT: .long __ZN1C4bee1Ev
-// CHECK-LP32-NEXT: .long __ZN1C4bee2Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .long __ZTI7test4_D
-// CHECK-LP32-NEXT: .long __ZN1B4bar1Ev
-// CHECK-LP32-NEXT: .long __ZN1B4bar2Ev
-
// CHECK-LP64:__ZTV7test4_D:
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad 8
@@ -277,58 +193,6 @@ struct test5_D : virtual test5_B1, virtual test5_B21, virtual test5_B31 {
virtual void funcD() { }
};
-// CHECK-LP32:__ZTV7test5_D:
-// CHECK-LP32-NEXT: .long 16
-// CHECK-LP32-NEXT: .long 12
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI7test5_D
-// CHECK-LP32-NEXT: .long __ZN8test5_B36funcB3Ev
-// CHECK-LP32-NEXT: .long __ZN8test5_B26funcB2Ev
-// CHECK-LP32-NEXT: .long __ZN8test5_B16funcB1Ev
-// CHECK-LP32-NEXT: .long __ZN7test5_D5funcDEv
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .long __ZTI7test5_D
-// CHECK-LP32-NEXT: .long __ZN9test5_B237funcB23Ev
-// CHECK-LP32-NEXT: .long __ZN9test5_B227funcB22Ev
-// CHECK-LP32-NEXT: .long __ZN9test5_B217funcB21Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .long __ZTI7test5_D
-// CHECK-LP32-NEXT: .long __ZN9test5_B337funcB33Ev
-// CHECK-LP32-NEXT: .long __ZN9test5_B327funcB32Ev
-// CHECK-LP32-NEXT: .long __ZN9test5_B317funcB31Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long __ZTI7test5_D
-// CHECK-LP32-NEXT: .long __ZN4B2328funcB232Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967280
-// CHECK-LP32-NEXT: .long __ZTI7test5_D
-// CHECK-LP32-NEXT: .long __ZN4B2318funcB231Ev
-
// CHECK-LP64:__ZTV7test5_D:
// CHECK-LP64-NEXT: .quad 32
// CHECK-LP64-NEXT: .quad 24
@@ -407,33 +271,6 @@ struct test8_B3 {
class test8_D : test8_B1, test8_B2, test8_B3 {
};
-// CHECK-LP32:__ZTV7test8_D:
-// CHECK-LP32-NEXT: .long 24
-// CHECK-LP32-NEXT: .long 16
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI7test8_D
-// CHECK-LP32-NEXT: .long __ZN8test8_B19ftest8_B1Ev
-// CHECK-LP32-NEXT: .long 20
-// CHECK-LP32-NEXT: .long 12
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .long __ZTI7test8_D
-// CHECK-LP32-NEXT: .long __ZN9test8_B2a10ftest8_B2aEv
-// CHECK-LP32-NEXT: .long __ZN8test8_B29ftest8_B2Ev
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .long __ZTI7test8_D
-// CHECK-LP32-NEXT: .long __ZN9test8_B2b10ftest8_B2bEv
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long __ZTI7test8_D
-// CHECK-LP32-NEXT: .long __ZN8test8_B39ftest8_B3Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967280
-// CHECK-LP32-NEXT: .long __ZTI7test8_D
-// CHECK-LP32-NEXT: .long __ZN10test8_B2aa11ftest8_B2aaEv
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967272
-// CHECK-LP32-NEXT: .long __ZTI7test8_D
-// CHECK-LP32-NEXT: .long __ZN10test8_B2ab11ftest8_B2abEv
-
// CHECK-LP64:__ZTV7test8_D:
// CHECK-LP64-NEXT: .quad 48
// CHECK-LP64-NEXT: .quad 32
@@ -461,6 +298,49 @@ class test8_D : test8_B1, test8_B2, test8_B3 {
// 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
+
struct test9_B3 { virtual void funcB3(); int i; };
struct test9_B2 : virtual test9_B3 { virtual void funcB2(); int i; };
@@ -554,77 +434,6 @@ struct test9_D : virtual test9_B1, virtual test9_B21, virtual test9_B31 {
// CHECK-LP64-NEXT: .quad __ZTI7test9_D
// CHECK-LP64-NEXT: .quad __ZN10test9_B2318funcB231Ev
-// CHECK-LP32: __ZTV7test9_D:
-// CHECK-LP32-NEXT: .long 84
-// CHECK-LP32-NEXT: .long 76
-// CHECK-LP32-NEXT: .long 68
-// CHECK-LP32-NEXT: .long 60
-// CHECK-LP32-NEXT: .long 52
-// CHECK-LP32-NEXT: .long 44
-// CHECK-LP32-NEXT: .long 36
-// CHECK-LP32-NEXT: .long 28
-// CHECK-LP32-NEXT: .long 20
-// CHECK-LP32-NEXT: .long 12
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN7test9_D5funcDEv
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 16
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN8test9_B16funcB1Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN8test9_B26funcB2Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967276
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN8test9_B36funcB3Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 16
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967268
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN9test9_B217funcB21Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967260
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN9test9_B227funcB22Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967252
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN9test9_B237funcB23Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 32
-// CHECK-LP32-NEXT: .long 24
-// CHECK-LP32-NEXT: .long 16
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967244
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN9test9_B317funcB31Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 16
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967236
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN9test9_B327funcB32Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967228
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN9test9_B337funcB33Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967220
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN10test9_B2328funcB232Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967212
-// CHECK-LP32-NEXT: .long __ZTI7test9_D
-// CHECK-LP32-NEXT: .long __ZN10test9_B2318funcB231Ev
struct test10_O { int i; };
@@ -673,26 +482,6 @@ class test10_D : test10_B1, test10_B2 {
// CHECK-LP64-NEXT: .quad 18446744073709551576
// CHECK-LP64-NEXT: .quad __ZTI8test10_D
-// CHECK-LP32: __ZTV8test10_D:
-// CHECK-LP32-NEXT: .long 20
-// CHECK-LP32-NEXT: .long 12
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI8test10_D
-// CHECK-LP32-NEXT: .long __ZN9test10_B110ftest10_B1Ev
-// CHECK-LP32-NEXT: .long 16
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .long __ZTI8test10_D
-// CHECK-LP32-NEXT: .long __ZN10test10_B2a11ftest10_B2aEv
-// CHECK-LP32-NEXT: .long __ZN9test10_B210ftest10_B2Ev
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long __ZTI8test10_D
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long 4294967276
-// CHECK-LP32-NEXT: .long __ZTI8test10_D
struct test11_B {
virtual void B1() { }
@@ -706,16 +495,6 @@ struct test11_D : test11_B {
virtual void D2() { }
};
-// CHECK-LP32:__ZTV8test11_D:
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI8test11_D
-// CHECK-LP32-NEXT: .long __ZN8test11_B2B1Ev
-// CHECK-LP32-NEXT: .long __ZN8test11_D1DEv
-// CHECK-LP32-NEXT: .long __ZN8test11_B2B2Ev
-// CHECK-LP32-NEXT: .long __ZN8test11_D2D1Ev
-// CHECK-LP32-NEXT: .long __ZN8test11_D2D2Ev
-
-
// CHECK-LP64:__ZTV8test11_D:
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad __ZTI8test11_D
@@ -803,47 +582,6 @@ struct test13_D : test13_NV1, virtual test13_B2 {
// CHECK-LP64-NEXT: .quad __ZN8test13_B2DcEv
// CHECK-LP64-NEXT: .quad __ZTv0_n64_N9test13_B22B2Ev
-// CHECK-LP32:__ZTV8test13_D:
-// CHECK-LP32-NEXT: .long 12
-// CHECK-LP32-NEXT: .long 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI8test13_D
-// CHECK-LP32-NEXT: .long __ZN8test13_D6fooNV1Ev
-// CHECK-LP32-NEXT: .long __ZN8test13_D1DEv
-// CHECK-LP32-NEXT: .long __ZN8test13_D2D1Ev
-// CHECK-LP32-NEXT: .long __ZN8test13_D2DbEv
-// CHECK-LP32-NEXT: .long __ZN8test13_D2DdEv
-// CHECK-LP32-NEXT: .long __ZN8test13_D2D2Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .long 4294967292
-// CHECK-LP32-NEXT: .long __ZTI8test13_D
-// CHECK-LP32-NEXT: .long __ZN9test13_B23B2aEv
-// CHECK-LP32-NEXT: .long __ZN9test13_B22B2Ev
-// CHECK-LP32-NEXT: .long __ZTv0_n24_N8test13_D1DEv
-// CHECK-LP32-NEXT: .long __ZN9test13_B22DaEv
-// CHECK-LP32-NEXT: .long __ZTv0_n32_N8test13_D2DdEv
-// CHECK-LP32-NEXT: .long __ZN9test13_B23B2bEv
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long __ZTI8test13_D
-// CHECK-LP32-NEXT: .long __ZN8test13_B2B1Ev
-// CHECK-LP32-NEXT: .long __ZTv0_n16_N8test13_D1DEv
-// CHECK-LP32-NEXT: .long __ZTv0_n20_N9test13_B22DaEv
-// CHECK-LP32-NEXT: .long __ZTv0_n24_N8test13_D2DbEv
-// CHECK-LP32-NEXT: .long __ZN8test13_B2DcEv
-// CHECK-LP32-NEXT: .long __ZTv0_n32_N9test13_B22B2Ev
-
class test14 {
public:
@@ -907,31 +645,6 @@ struct test15_D : test15_NV1, virtual test15_B2 {
// CHECK-LP64-NEXT: .quad __ZTcv0_n32_v0_n24_N9test15_B24foo2Ev
// CHECK-LP64-NEXT: .quad __ZN8test15_B4foo3Ev
-// CHECK-LP32:__ZTV8test15_D:
-// CHECK-LP32-NEXT: .long 20
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI8test15_D
-// CHECK-LP32-NEXT: .long __ZN10test15_NV16fooNV1Ev
-// CHECK-LP32-NEXT: .long __ZN8test15_D4foo1Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 12
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .long __ZTI8test15_D
-// CHECK-LP32-NEXT: .long __ZN10test15_NV16fooNV1Ev
-// CHECK-LP32-NEXT: .long __ZTcv0_n20_v0_n12_N8test15_D4foo1Ev
-// CHECK-LP32-NEXT: .long __ZN9test15_B24foo2Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long 4294967276
-// CHECK-LP32-NEXT: .long 4294967276
-// CHECK-LP32-NEXT: .long __ZTI8test15_D
-// CHECK-LP32-NEXT: .long __ZTcv0_n12_v0_n16_N8test15_D4foo1Ev
-// CHECK-LP32-NEXT: .long __ZTcv0_n16_v0_n12_N9test15_B24foo2Ev
-// CHECK-LP32-NEXT: .long __ZN8test15_B4foo3Ev
-
struct test16_NV1 {
virtual void fooNV1() { }
@@ -995,7 +708,7 @@ void test16_D::bar() { }
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64: .quad 18446744073709551600
-// CHECK-LP64: .quad 18446744073709551584
+// CHECK-LP64-NEXT: .quad 18446744073709551584
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad 18446744073709551584
@@ -1012,80 +725,60 @@ void test16_D::bar() { }
// CHECK-LP64: .quad __ZN10test16_NV27foo_NV2Ev
// CHECK-LP64-NEXT: .quad __ZN10test16_NV28foo_NV2bEv
-// CHECK-LP32: __ZTV8test16_D:
-// CHECK-LP32-NEXT: .long 20
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI8test16_D
-// CHECK-LP32-NEXT: .long __ZN10test16_NV16fooNV1Ev
-// CHECK-LP32-NEXT: .long __ZN10test16_NV17foo_NV1Ev
-// CHECK-LP32-NEXT: .long __ZN8test16_D3barEv
-// CHECK-LP32-NEXT: .long __ZN8test16_D4foo1Ev
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 12
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .long __ZTI8test16_D
-// CHECK-LP32-NEXT: .long __ZN10test16_NV16fooNV1Ev
-// CHECK-LP32-NEXT: .long __ZN10test16_NV17foo_NV1Ev
-// CHECK-LP32-NEXT: .long __ZTcv0_n24_v0_n12_N8test16_D4foo1Ev
-// CHECK-LP32-NEXT: .long __ZN9test16_B24foo2Ev
-// CHECK-LP32-NEXT: .long __ZN9test16_B26foo_B2Ev
-// CHECK-LP32-NEXT .long 8
-// CHECK-LP32-NEXT .long 8
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32: .long 4294967284
-// CHECK-LP32-NEXT: .long 4294967276
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967276
-// CHECK-LP32-NEXT: .long __ZTI8test16_D
-// CHECK-LP32-NEXT: .long __ZN10test16_NV16fooNV1Ev
-// CHECK-LP32-NEXT: .long __ZN10test16_NV17foo_NV1Ev
-// CHECK-LP32-NEXT: .long __ZTcv0_n20_v0_n16_N8test16_D4foo1Ev
-// CHECK-LP32-NEXT: .long __ZTcv0_n24_v0_n12_N9test16_B24foo2Ev
-// CHECK-LP32-NEXT: .long __ZN8test16_B4foo3Ev
-// CHECK-LP32-NEXT: .long __ZN8test16_B5foo_BEv
-// CHECK-LP32-NEXT: .long 4294967268
-// CHECK-LP32-NEXT: .long __ZTI8test16_D
-// CHECK-LP32-NEXT .long __ZTcvn8_n20_v8_n16_N8test16_D4foo1Ev
-// CHECK-LP32: .long __ZN10test16_NV27foo_NV2Ev
-// CHECK-LP32-NEXT: .long __ZN10test16_NV28foo_NV2bEv
-
// FIXME: This is the wrong thunk, but until these issues are fixed, better
// than nothing.
-// CHECK-LPOPT64: __ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev:
-// CHECK-LPOPT64-NEXT:Leh_func_begin
-// CHECK-LPOPT64-NEXT: subq $8, %rsp
-// CHECK-LPOPT64-NEXT:Llabel
-// CHECK-LPOPT64-NEXT: movq -16(%rdi), %rax
-// CHECK-LPOPT64-NEXT: movq -72(%rax), %rax
-// CHECK-LPOPT64-NEXT: leaq -16(%rax,%rdi), %rdi
-// FIXME: We want a tail call here
-// CHECK-LPOPT64-NEXT: call __ZTch0_v16_n32_N8test16_D4foo1Ev
-// CHECK-LPOPT64-NEXT: addq $8, %rsp
-// CHECK-LPOPT64-NEXT: ret
-
-// CHECK-LPOPT64: __ZTch0_v16_n32_N8test16_D4foo1Ev:
-// CHECK-LPOPT64-NEXT:Leh_func_begin
-// CHECK-LPOPT64-NEXT: subq $8, %rsp
-// CHECK-LPOPT64-NEXT:Llabel
-// CHECK-LPOPT64-NEXT: call __ZN8test16_D4foo1Ev
-// CHECK-LPOPT64-NEXT: testq %rax, %rax
-// CHECK-LPOPT64-NEXT: je LBB102_2
-// CHECK-LPOPT64-NEXT: movq 16(%rax), %rcx
-// CHECK-LPOPT64-NEXT: movq -32(%rcx), %rcx
-// CHECK-LPOPT64-NEXT: leaq 16(%rcx,%rax), %rax
-// CHECK-LPOPT64-NEXT: addq $8, %rsp
-// CHECK-LPOPT64-NEXT: ret
-// CHECK-LPOPT64-NEXT:LBB102_2:
-// CHECK-LPOPT64-NEXT: addq $8, %rsp
-// CHECK-LPOPT64-NEXT: ret
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*) {
+// CHECK-LPLL64:entry:
+// CHECK-LPLL64: %retval = 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 = load %class.test8_D** %.addr
+// CHECK-LPLL64: %1 = bitcast %class.test8_D* %this to i8*
+// CHECK-LPLL64: %2 = getelementptr inbounds i8* %1, i64 -16
+// CHECK-LPLL64: %3 = bitcast i8* %2 to %class.test8_D*
+// CHECK-LPLL64: %4 = bitcast %class.test8_D* %3 to i8*
+// CHECK-LPLL64: %5 = bitcast %class.test8_D* %3 to i64**
+// CHECK-LPLL64: %vtable = load i64** %5
+// CHECK-LPLL64: %6 = getelementptr inbounds i64* %vtable, i64 -9
+// CHECK-LPLL64: %7 = load i64* %6
+// CHECK-LPLL64: %8 = getelementptr i8* %4, i64 %7
+// CHECK-LPLL64: %9 = bitcast i8* %8 to %class.test8_D*
+// CHECK-LPLL64: %call = call %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D* %9)
+// CHECK-LPLL64: store %class.test8_D* %call, %class.test8_D** %retval
+// CHECK-LPLL64: %10 = load %class.test8_D** %retval
+// CHECK-LPLL64: ret %class.test8_D* %10
+// CHECK-LPLL64:}
+
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D*) {
+// CHECK-LPLL64:entry:
+// CHECK-LPLL64: %retval = 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 = load %class.test8_D** %.addr
+// CHECK-LPLL64: %call = call %class.test8_D* @_ZN8test16_D4foo1Ev(%class.test8_D* %this)
+// CHECK-LPLL64: %1 = icmp ne %class.test8_D* %call, null
+// CHECK-LPLL64: br i1 %1, label %2, label %12
+// CHECK-LPLL64:; <label>:2
+// CHECK-LPLL64: %3 = bitcast %class.test8_D* %call to i8*
+// CHECK-LPLL64: %4 = getelementptr inbounds i8* %3, i64 16
+// CHECK-LPLL64: %5 = bitcast i8* %4 to %class.test8_D*
+// CHECK-LPLL64: %6 = bitcast %class.test8_D* %5 to i8*
+// CHECK-LPLL64: %7 = bitcast %class.test8_D* %5 to i64**
+// CHECK-LPLL64: %vtable = load i64** %7
+// CHECK-LPLL64: %8 = getelementptr inbounds i64* %vtable, i64 -4
+// CHECK-LPLL64: %9 = load i64* %8
+// CHECK-LPLL64: %10 = getelementptr i8* %6, i64 %9
+// CHECK-LPLL64: %11 = bitcast i8* %10 to %class.test8_D*
+// CHECK-LPLL64: br label %13
+// CHECK-LPLL64:; <label>:12
+// CHECK-LPLL64: br label %13
+// CHECK-LPLL64:; <label>:13
+// CHECK-LPLL64: %14 = phi %class.test8_D* [ %11, %2 ], [ %call, %12 ]
+// CHECK-LPLL64: store %class.test8_D* %14, %class.test8_D** %retval
+// CHECK-LPLL64: %15 = load %class.test8_D** %retval
+// CHECK-LPLL64: ret %class.test8_D* %15
+// CHECK-LPLL64:}
class test17_B1 {
@@ -1220,16 +913,27 @@ struct test19_D : virtual test19_B4 {
// 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-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-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
class test20_V {
@@ -1243,7 +947,7 @@ class test20_B : virtual test20_V {
class test20_B1 : virtual test20_V1 {
};
class test20_D : public test20_B, public test20_B1 {
-} d;
+};
// CHECK-LP64: __ZTV8test20_D:
// CHECK-LP64-NEXT: .quad 8
@@ -1258,6 +962,82 @@ class test20_D : public test20_B, public test20_B1 {
// 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-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
+
+
+class test21_V {
+ virtual void foo() { }
+};
+class test21_V1 {
+ virtual void foo() { }
+};
+class test21_B : virtual test21_V {
+};
+class test21_B1 : virtual test21_V1 {
+};
+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-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: __ZTV1B:
@@ -1266,12 +1046,6 @@ class test20_D : public test20_B, public test20_B1 {
// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev
// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev
-// CHECK-LP32: __ZTV1B:
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI1B
-// CHECK-LP32-NEXT: .long __ZN1B4bar1Ev
-// CHECK-LP32-NEXT: .long __ZN1B4bar2Ev
-
// CHECK-LP64: __ZTV1A:
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad __ZTI1A
@@ -1284,39 +1058,6 @@ class test20_D : public test20_B, public test20_B1 {
// CHECK-LP64-NEXT: .quad __ZN1C4bee1Ev
// CHECK-LP64-NEXT: .quad __ZN1C4bee2Ev
-// CHECK-LP32: __ZTV1A:
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI1A
-// CHECK-LP32-NEXT: .long __ZN1B4bar1Ev
-// CHECK-LP32-NEXT: .long __ZN1B4bar2Ev
-// CHECK-LP32-NEXT: .long __ZN1A4foo1Ev
-// CHECK-LP32-NEXT: .long __ZN1A4foo2Ev
-// CHECK-LP32-NEXT: .long 4294967284
-// CHECK-LP32-NEXT: .long __ZTI1A
-// CHECK-LP32-NEXT: .long __ZN1C4bee1Ev
-// CHECK-LP32-NEXT: .long __ZN1C4bee2Ev
-
-// CHECK-LP32:__ZTV1F:
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 8
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long __ZTI1F
-// CHECK-LP32-NEXT: .long __ZN1D3booEv
-// CHECK-LP32-NEXT: .long __ZN1F3fooEv
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT: .long 4294967288
-// CHECK-LP32-NEXT: .long __ZTI1F
-// CHECK-LP32-NEXT: .long __ZN2D13barEv
-// CHECK-LP32-NEXT: .long __ZN2D14bar2Ev
-// CHECK-LP32-NEXT: .long __ZN2D14bar3Ev
-// CHECK-LP32-NEXT: .long __ZN2D14bar4Ev
-// CHECK-LP32-NEXT: .long __ZN2D14bar5Ev
-
// CHECK-LP64: __ZTV1F:
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad 16
@@ -1338,6 +1079,8 @@ class test20_D : public test20_B, public test20_B1 {
// CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev
// CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev
+test21_D d21;
+test20_D d20;
test19_D d19;
test18_D d18;
test17_D d17;
diff --git a/test/CodeGenCXX/virtual-operator-call.cpp b/test/CodeGenCXX/virtual-operator-call.cpp
new file mode 100644
index 000000000000..018052bb472c
--- /dev/null
+++ b/test/CodeGenCXX/virtual-operator-call.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
+
+struct A {
+ virtual int operator-() = 0;
+};
+
+void f(A *a) {
+ // CHECK: call i32 %
+ -*a;
+}
diff --git a/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp
new file mode 100644
index 000000000000..3d99a0216073
--- /dev/null
+++ b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
+
+struct A {
+ virtual ~A();
+};
+
+void f(A *a) {
+ // CHECK: call void %
+ a->~A();
+}
diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp
index 426c867a7b6b..6b5e7a7a1d2c 100644
--- a/test/CodeGenCXX/x86_64-arguments.cpp
+++ b/test/CodeGenCXX/x86_64-arguments.cpp
@@ -1,10 +1,9 @@
-// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s
struct A { ~A(); };
-// RUN: grep 'define void @_Z2f11A(.struct.A\* .a)' %t &&
+// RUN: grep 'define void @_Z2f11A(.struct.A\* .a)' %t
void f1(A a) { }
-// RUN: grep 'define void @_Z2f2v(.struct.A\* noalias sret .agg.result)' %t &&
+// RUN: grep 'define void @_Z2f2v(.struct.A\* noalias sret .agg.result)' %t
A f2() { return A(); }
-// RUN: true
diff --git a/test/CodeGenObjC/bitfield-1.m b/test/CodeGenObjC/bitfield-1.m
index 06ea91132ef3..3f605ebc4e24 100644
--- a/test/CodeGenObjC/bitfield-1.m
+++ b/test/CodeGenObjC/bitfield-1.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s
// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s
@interface Object
diff --git a/test/CodeGenObjC/bitfield-ivar-metadata.m b/test/CodeGenObjC/bitfield-ivar-metadata.m
index 542a2424caa1..f720bcc5b5b6 100644
--- a/test/CodeGenObjC/bitfield-ivar-metadata.m
+++ b/test/CodeGenObjC/bitfield-ivar-metadata.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
@interface INTF
{
diff --git a/test/CodeGenObjC/bitfield-ivar-offsets.m b/test/CodeGenObjC/bitfield-ivar-offsets.m
index 23a09a3a15b8..f4bc39d4fb05 100644
--- a/test/CodeGenObjC/bitfield-ivar-offsets.m
+++ b/test/CodeGenObjC/bitfield-ivar-offsets.m
@@ -1,14 +1,13 @@
// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0._b0" = global i64 0, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0._b1" = global i64 0, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0._b2" = global i64 1, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0._x" = global i64 2, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0._b3" = global i64 4, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0._y" = global i64 6, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0._b4" = global i64 7, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep -F '@"OBJC_IVAR_$_I0." = global' %t | count 0 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s
+// RUN: grep -F '@"OBJC_IVAR_$_I0._b0" = global i64 0, section "__DATA, __objc_const", align 8' %t
+// RUN: grep -F '@"OBJC_IVAR_$_I0._b1" = global i64 0, section "__DATA, __objc_const", align 8' %t
+// RUN: grep -F '@"OBJC_IVAR_$_I0._b2" = global i64 1, section "__DATA, __objc_const", align 8' %t
+// RUN: grep -F '@"OBJC_IVAR_$_I0._x" = global i64 2, section "__DATA, __objc_const", align 8' %t
+// RUN: grep -F '@"OBJC_IVAR_$_I0._b3" = global i64 4, section "__DATA, __objc_const", align 8' %t
+// RUN: grep -F '@"OBJC_IVAR_$_I0._y" = global i64 6, section "__DATA, __objc_const", align 8' %t
+// RUN: grep -F '@"OBJC_IVAR_$_I0._b4" = global i64 7, section "__DATA, __objc_const", align 8' %t
+// RUN: grep -F '@"OBJC_IVAR_$_I0." = global' %t | count 0
@interface I0 {
unsigned _b0:4;
diff --git a/test/CodeGenObjC/blocks-1.m b/test/CodeGenObjC/blocks-1.m
index 2b4f8faeb82e..ee1b97801b42 100644
--- a/test/CodeGenObjC/blocks-1.m
+++ b/test/CodeGenObjC/blocks-1.m
@@ -1,12 +1,12 @@
-// RUN: clang-cc %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 &&
-// RUN: grep "_Block_object_dispose" %t | count 6 &&
-// RUN: grep "__copy_helper_block_" %t | count 4 &&
-// RUN: grep "__destroy_helper_block_" %t | count 4 &&
-// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 &&
-// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 &&
-// RUN: grep "i32 135)" %t | count 0 &&
-// RUN: grep "_Block_object_assign" %t | count 4 &&
-// RUN: grep "objc_read_weak" %t | count 2 &&
+// RUN: clang-cc %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10
+// RUN: grep "_Block_object_dispose" %t | count 6
+// RUN: grep "__copy_helper_block_" %t | count 4
+// RUN: grep "__destroy_helper_block_" %t | count 4
+// RUN: grep "__Block_byref_id_object_copy_" %t | count 2
+// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2
+// RUN: grep "i32 135)" %t | count 0
+// RUN: grep "_Block_object_assign" %t | count 4
+// RUN: grep "objc_read_weak" %t | count 2
// RUN: grep "objc_assign_weak" %t | count 3
@interface NSDictionary @end
diff --git a/test/CodeGenObjC/blocks-2.m b/test/CodeGenObjC/blocks-2.m
index a4d8bfa6b7fc..bb7af99416f3 100644
--- a/test/CodeGenObjC/blocks-2.m
+++ b/test/CodeGenObjC/blocks-2.m
@@ -1,6 +1,5 @@
-// RUN: clang-cc %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 &&
-// RUN: grep "objc_assign_strongCast" %t | count 2 &&
-// RUN: true
+// RUN: clang-cc %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10
+// RUN: grep "objc_assign_strongCast" %t | count 2
// This should generate a strong cast.
diff --git a/test/CodeGenObjC/blocks-3.m b/test/CodeGenObjC/blocks-3.m
index 96e436b5fb64..16da55ed6322 100644
--- a/test/CodeGenObjC/blocks-3.m
+++ b/test/CodeGenObjC/blocks-3.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -fblocks -o %t %s &&
-// RUN: grep 'object_assign' %t | count 11 &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -fblocks -o %t %s
+// RUN: grep 'object_assign' %t | count 11
// RUN: grep 'object_dispose' %t | count 29
int main() {
diff --git a/test/CodeGenObjC/blocks.m b/test/CodeGenObjC/blocks.m
index 18c455ad9ebe..def4c9dd7a70 100644
--- a/test/CodeGenObjC/blocks.m
+++ b/test/CodeGenObjC/blocks.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -fblocks -o %t %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -fblocks -o %t %s
// rdar://6676764
struct S {
@@ -19,7 +19,7 @@ void foo(T *P) {
-(void) im0;
@end
-// RUN: grep 'define internal i32 @"__-\[A im0\]_block_invoke_"' %t &&
+// RUN: grep 'define internal i32 @"__-\[A im0\]_block_invoke_"' %t
@implementation A
-(void) im0 {
(void) ^{ return 1; }();
@@ -33,4 +33,3 @@ void foo(T *P) {
}
@end
-// RUN: true
diff --git a/test/CodeGenObjC/category-super-class-meth.m b/test/CodeGenObjC/category-super-class-meth.m
index 95d8b3103c9f..ce27e87bbf50 100644
--- a/test/CodeGenObjC/category-super-class-meth.m
+++ b/test/CodeGenObjC/category-super-class-meth.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
@interface BASE
+ (int) BaseMeth;
diff --git a/test/CodeGenObjC/class-getter-dotsyntax.m b/test/CodeGenObjC/class-getter-dotsyntax.m
index 3c82f78d08b5..1e1a7596795e 100644
--- a/test/CodeGenObjC/class-getter-dotsyntax.m
+++ b/test/CodeGenObjC/class-getter-dotsyntax.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
@interface Test { }
+ (Test *)crash;
diff --git a/test/CodeGenObjC/class-type.m b/test/CodeGenObjC/class-type.m
index 794d9a355794..d63f8420d280 100644
--- a/test/CodeGenObjC/class-type.m
+++ b/test/CodeGenObjC/class-type.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o - %s &&
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o - %s &&
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o - %s
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o - %s
// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o - %s
diff --git a/test/CodeGenObjC/constant-strings.m b/test/CodeGenObjC/constant-strings.m
index 82cd916b5ca8..8482376ff913 100644
--- a/test/CodeGenObjC/constant-strings.m
+++ b/test/CodeGenObjC/constant-strings.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: clang-cc -fgnu-runtime -emit-llvm -o %t %s && grep NXConstantString %t | count 1 &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: clang-cc -fgnu-runtime -emit-llvm -o %t %s && grep NXConstantString %t | count 1
// RUN: clang-cc -fgnu-runtime -fconstant-string-class=NSConstantString -emit-llvm -o %t %s && grep NSConstantString %t | count 1
id a = @"Hello World!";
diff --git a/test/CodeGenObjC/continuation-class.m b/test/CodeGenObjC/continuation-class.m
index 925f3cd0c50d..305d6c7ab39a 100644
--- a/test/CodeGenObjC/continuation-class.m
+++ b/test/CodeGenObjC/continuation-class.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
@interface Object
- (id)new;
diff --git a/test/CodeGenObjC/deadcode_strip_used_var.m b/test/CodeGenObjC/deadcode_strip_used_var.m
index 444cf766f7dd..d2548fdec85b 100644
--- a/test/CodeGenObjC/deadcode_strip_used_var.m
+++ b/test/CodeGenObjC/deadcode_strip_used_var.m
@@ -1,6 +1,6 @@
-// RUN: clang-cc %s -emit-llvm -o %t -triple i386-apple-darwin10 &&
-// RUN: grep "llvm.used" %t | count 1 &&
-// RUN: clang-cc %s -emit-llvm -o %t -triple x86_64-apple-darwin10 &&
+// RUN: clang-cc %s -emit-llvm -o %t -triple i386-apple-darwin10
+// RUN: grep "llvm.used" %t | count 1
+// RUN: clang-cc %s -emit-llvm -o %t -triple x86_64-apple-darwin10
// RUN: grep "llvm.used" %t | count 1
diff --git a/test/CodeGenObjC/debug-info-linkagename.m b/test/CodeGenObjC/debug-info-linkagename.m
index 730568954cb0..bda98eec49b5 100644
--- a/test/CodeGenObjC/debug-info-linkagename.m
+++ b/test/CodeGenObjC/debug-info-linkagename.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -g -S -o %t %s &&
+// RUN: clang-cc -g -S -o %t %s
// RUN: not grep 001 %t
@interface F
diff --git a/test/CodeGenObjC/dot-syntax-1.m b/test/CodeGenObjC/dot-syntax-1.m
index 6c4dcbbef0dc..6fab03935bea 100644
--- a/test/CodeGenObjC/dot-syntax-1.m
+++ b/test/CodeGenObjC/dot-syntax-1.m
@@ -1,6 +1,6 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
-#include <stdio.h>
+int printf(const char *, ...);
@interface Root
-(id) alloc;
diff --git a/test/CodeGenObjC/dot-syntax.m b/test/CodeGenObjC/dot-syntax.m
index 68c8ad0b7580..348346b8fca2 100644
--- a/test/CodeGenObjC/dot-syntax.m
+++ b/test/CodeGenObjC/dot-syntax.m
@@ -1,6 +1,6 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
-#include <stdio.h>
+int printf(const char *, ...);
@interface Root
-(id) alloc;
diff --git a/test/CodeGenObjC/encode-test-1.m b/test/CodeGenObjC/encode-test-1.m
index b4f3b0f9c33d..8e6fd861f9cc 100644
--- a/test/CodeGenObjC/encode-test-1.m
+++ b/test/CodeGenObjC/encode-test-1.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep -e "{Base=b2b3b4b5}" %t | count 1 &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep -e "{Base=b2b3b4b5}" %t | count 1
// RUN: grep -e "{Derived=b2b3b4b5b5b4b3}" %t | count 1
enum Enum { one, two, three, four };
diff --git a/test/CodeGenObjC/encode-test-2.m b/test/CodeGenObjC/encode-test-2.m
index 07a53367557a..b53ea6677ebd 100644
--- a/test/CodeGenObjC/encode-test-2.m
+++ b/test/CodeGenObjC/encode-test-2.m
@@ -1,8 +1,8 @@
-// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep -e "@\\\22<X>\\\22" %t &&
-// RUN: grep -e "@\\\22<X><Y>\\\22" %t &&
-// RUN: grep -e "@\\\22<X><Y><Z>\\\22" %t &&
-// RUN: grep -e "@\\\22Foo<X><Y><Z>\\\22" %t &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep -e "@\\\22<X>\\\22" %t
+// RUN: grep -e "@\\\22<X><Y>\\\22" %t
+// RUN: grep -e "@\\\22<X><Y><Z>\\\22" %t
+// RUN: grep -e "@\\\22Foo<X><Y><Z>\\\22" %t
// RUN: grep -e "{Intf=@@@@#}" %t
@protocol X, Y, Z;
diff --git a/test/CodeGenObjC/encode-test-3.m b/test/CodeGenObjC/encode-test-3.m
index 116e825e32a0..79a024fe1f7b 100644
--- a/test/CodeGenObjC/encode-test-3.m
+++ b/test/CodeGenObjC/encode-test-3.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep -e "\^i" %t | count 1 &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep -e "\^i" %t | count 1
// RUN: grep -e "\[0i\]" %t | count 1
int main() {
diff --git a/test/CodeGenObjC/encode-test-5.m b/test/CodeGenObjC/encode-test-5.m
index 9820b4183f32..d5ec9b3909c7 100644
--- a/test/CodeGenObjC/encode-test-5.m
+++ b/test/CodeGenObjC/encode-test-5.m
@@ -1,15 +1,15 @@
-// RUN: clang-cc -triple=x86_64-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple=x86_64-apple-darwin9 -emit-llvm -o %t %s
-// RUN: grep ji.00 %t | count 1 &&
+// RUN: grep ji.00 %t | count 1
char *a = @encode(_Complex int);
-// RUN: grep jf.00 %t | count 1 &&
+// RUN: grep jf.00 %t | count 1
char *b = @encode(_Complex float);
-// RUN: grep jd.00 %t | count 1 &&
+// RUN: grep jd.00 %t | count 1
char *c = @encode(_Complex double);
-// RUN: grep "t.00" %t | count 1 &&
+// RUN: grep "t.00" %t | count 1
char *e = @encode(__int128_t);
// RUN: grep "T.00" %t | count 1
diff --git a/test/CodeGenObjC/encode-test.m b/test/CodeGenObjC/encode-test.m
index ca54a51c3b1c..6665cb9d584b 100644
--- a/test/CodeGenObjC/encode-test.m
+++ b/test/CodeGenObjC/encode-test.m
@@ -1,9 +1,9 @@
-// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep -e "\^{Innermost=CC}" %t | count 1 &&
-// RUN: grep -e "{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}" %t | count 1 &&
-// RUN: grep -e "{B1=#@c}" %t | count 1 &&
-// RUN: grep -e "v12@0:4\[3\[4@]]8" %t | count 1 &&
-// RUN: grep -e "r\^{S=i}" %t | count 1 &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep -e "\^{Innermost=CC}" %t | count 1
+// RUN: grep -e "{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}" %t | count 1
+// RUN: grep -e "{B1=#@c}" %t | count 1
+// RUN: grep -e "v12@0:4\[3\[4@]]8" %t | count 1
+// RUN: grep -e "r\^{S=i}" %t | count 1
// RUN: grep -e "\^{Object=#}" %t | count 1
@class Int1;
diff --git a/test/CodeGenObjC/forward-class-impl-metadata.m b/test/CodeGenObjC/forward-class-impl-metadata.m
index b8ce10aaa510..5dfddde89486 100644
--- a/test/CodeGenObjC/forward-class-impl-metadata.m
+++ b/test/CodeGenObjC/forward-class-impl-metadata.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s
+// RUN: clang-cc -fobjc-nonfragile-abi -emit-llvm -o %t %s
@interface BASE {
@private
diff --git a/test/CodeGenObjC/hidden-visibility.m b/test/CodeGenObjC/hidden-visibility.m
new file mode 100644
index 000000000000..082ee7a70a38
--- /dev/null
+++ b/test/CodeGenObjC/hidden-visibility.m
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fvisibility=hidden -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck %s
+// CHECK: @"OBJC_IVAR_$_I.P" = hidden
+// CHECK: @"OBJC_CLASS_$_I" = hidden
+// CHECK: @"OBJC_METACLASS_$_I" = hidden
+// CHECK: @"\01l_OBJC_PROTOCOL_$_Prot0" = weak hidden
+
+@interface I {
+ int P;
+}
+
+@property int P;
+@end
+
+@implementation I
+@synthesize P;
+@end
+
+
+@protocol Prot0;
+
+id f0() {
+ return @protocol(Prot0);
+}
+
+
diff --git a/test/CodeGenObjC/hidden.m b/test/CodeGenObjC/hidden.m
index 6b86ca0581cc..fd87d992aaf4 100644
--- a/test/CodeGenObjC/hidden.m
+++ b/test/CodeGenObjC/hidden.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
__attribute__((visibility("hidden")))
@interface Hidden
diff --git a/test/CodeGenObjC/image-info.m b/test/CodeGenObjC/image-info.m
index e8650129e3f7..c16f11d8bc01 100644
--- a/test/CodeGenObjC/image-info.m
+++ b/test/CodeGenObjC/image-info.m
@@ -1,2 +1,2 @@
-// RUN: clang-cc -triple x86_64-apple-darwin-10 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin-10 -emit-llvm -o %t %s
// RUN: grep -F '@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__OBJC, __image_info,regular"' %t
diff --git a/test/CodeGenObjC/implicit-objc_msgSend.m b/test/CodeGenObjC/implicit-objc_msgSend.m
index 4511cca338b2..f2fba58f4b57 100644
--- a/test/CodeGenObjC/implicit-objc_msgSend.m
+++ b/test/CodeGenObjC/implicit-objc_msgSend.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s
// RUN: grep -F 'declare i8* @objc_msgSend(...)' %t
typedef struct objc_selector *SEL;
diff --git a/test/CodeGenObjC/interface-layout-64.m b/test/CodeGenObjC/interface-layout-64.m
index 13d6a8770f65..ac29839a7920 100644
--- a/test/CodeGenObjC/interface-layout-64.m
+++ b/test/CodeGenObjC/interface-layout-64.m
@@ -1,28 +1,27 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s
// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s &&
-// RUN: grep '@"OBJC_IVAR_$_I3._iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I3._iv3" = global i64 12, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I4._iv4" = global i64 13, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I5._iv5" = global i64 14, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = global i64 16, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = global i64 20, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I6.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I8.b" = global i64 8, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I9.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I10.iv1" = global i64 4, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I12.iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I3" = internal global .* { i32 0, i32 8, i32 13, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I4" = internal global .* { i32 0, i32 13, i32 14, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I5" = internal global .* { i32 0, i32 14, i32 24, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I6" = internal global .* { i32 2, i32 0, i32 1, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I8" = internal global .* { i32 0, i32 8, i32 16, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I9" = internal global .* { i32 2, i32 0, i32 4, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I10" = internal global .* { i32 0, i32 4, i32 5, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I11" = internal global .* { i32 0, i32 5, i32 5, .*' %t &&
-// RUN: grep '_OBJC_CLASS_RO_$_I12" = internal global .* { i32 0, i32 8, i32 12, .*' %t &&
-
-// RUN: true
+// RUN: grep '@"OBJC_IVAR_$_I3._iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I3._iv3" = global i64 12, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I4._iv4" = global i64 13, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I5._iv5" = global i64 14, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = global i64 16, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = global i64 20, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I6.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I8.b" = global i64 8, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I9.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I10.iv1" = global i64 4, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_IVAR_$_I12.iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I3" = internal global .* { i32 0, i32 8, i32 13, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I4" = internal global .* { i32 0, i32 13, i32 14, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I5" = internal global .* { i32 0, i32 14, i32 24, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I6" = internal global .* { i32 2, i32 0, i32 1, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I8" = internal global .* { i32 0, i32 8, i32 16, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I9" = internal global .* { i32 2, i32 0, i32 4, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I10" = internal global .* { i32 0, i32 4, i32 5, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I11" = internal global .* { i32 0, i32 5, i32 5, .*' %t
+// RUN: grep '_OBJC_CLASS_RO_$_I12" = internal global .* { i32 0, i32 8, i32 12, .*' %t
+
/*
Compare to:
diff --git a/test/CodeGenObjC/interface.m b/test/CodeGenObjC/interface.m
index d506e88ee7c9..543c5354c372 100644
--- a/test/CodeGenObjC/interface.m
+++ b/test/CodeGenObjC/interface.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -O3 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -O3 -emit-llvm -o %t %s
// RUN: grep 'ret i32 385' %t
void *alloca();
diff --git a/test/CodeGenObjC/ivar-layout-64.m b/test/CodeGenObjC/ivar-layout-64.m
index 7301e168218e..190575316928 100644
--- a/test/CodeGenObjC/ivar-layout-64.m
+++ b/test/CodeGenObjC/ivar-layout-64.m
@@ -1,10 +1,9 @@
// RUNX: llvm-gcc -m64 -fobjc-gc -emit-llvm -S -o %t %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"A\\00"' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\11q\\10\\00"' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"!q\\00"' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\01\\14\\00"' %t &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"A\\00"' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\11q\\10\\00"' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"!q\\00"' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\01\\14\\00"' %t
/*
diff --git a/test/CodeGenObjC/ivar-layout-no-optimize.m b/test/CodeGenObjC/ivar-layout-no-optimize.m
index d7796bc279e1..2e04d7eaecb1 100644
--- a/test/CodeGenObjC/ivar-layout-no-optimize.m
+++ b/test/CodeGenObjC/ivar-layout-no-optimize.m
@@ -1,6 +1,5 @@
-// RUN: clang-cc -fobjc-gc -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: true
+// RUN: clang-cc -fobjc-gc -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
@interface NSObject {
id isa;
diff --git a/test/CodeGenObjC/ivars.m b/test/CodeGenObjC/ivars.m
index 327b628532e1..c7fcafd5353d 100644
--- a/test/CodeGenObjC/ivars.m
+++ b/test/CodeGenObjC/ivars.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o - %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o - %s
// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o - %s
// rdar://6800926
diff --git a/test/CodeGenObjC/link-errors.m b/test/CodeGenObjC/link-errors.m
index b50d93993fc8..4944f1b0782a 100644
--- a/test/CodeGenObjC/link-errors.m
+++ b/test/CodeGenObjC/link-errors.m
@@ -1,8 +1,8 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep '.lazy_reference .objc_class_name_A' %t | count 1 &&
-// RUN: grep '.lazy_reference .objc_class_name_Unknown' %t | count 1 &&
-// RUN: grep '.lazy_reference .objc_class_name_Protocol' %t | count 1 &&
-// RUN: clang-cc -triple i386-apple-darwin9 -DWITH_IMPL -fnext-runtime -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep '.lazy_reference .objc_class_name_A' %t | count 1
+// RUN: grep '.lazy_reference .objc_class_name_Unknown' %t | count 1
+// RUN: grep '.lazy_reference .objc_class_name_Protocol' %t | count 1
+// RUN: clang-cc -triple i386-apple-darwin9 -DWITH_IMPL -emit-llvm -o %t %s
// RUN: grep '.lazy_reference .objc_class_name_Root' %t | count 1
@interface Root
diff --git a/test/CodeGenObjC/message-arrays.m b/test/CodeGenObjC/message-arrays.m
index c618672feab2..1ae6bf648c8a 100644
--- a/test/CodeGenObjC/message-arrays.m
+++ b/test/CodeGenObjC/message-arrays.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
void f0(id a) {
// This should have an implicit cast
diff --git a/test/CodeGenObjC/messages-2.m b/test/CodeGenObjC/messages-2.m
index ca0eb9493387..5cf4d2df2213 100644
--- a/test/CodeGenObjC/messages-2.m
+++ b/test/CodeGenObjC/messages-2.m
@@ -1,6 +1,6 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
-#include <stdio.h>
+int printf(const char *, ...);
@interface Root
@end
diff --git a/test/CodeGenObjC/messages.m b/test/CodeGenObjC/messages.m
index b7f42d126d2b..ea8809ffcd18 100644
--- a/test/CodeGenObjC/messages.m
+++ b/test/CodeGenObjC/messages.m
@@ -1,10 +1,9 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s &&
-// RUN: grep "objc_msgSend" %t | count 6 &&
-// RUN: clang-cc -fgnu-runtime --emit-llvm -o %t %s &&
-// RUN: grep "objc_msg_lookup" %t | count 6 &&
-// RUN: clang-cc -fgnu-runtime -fobjc-nonfragile-abi --emit-llvm -o %t %s &&
-// RUN: grep "objc_msg_lookup_sender" %t | count 6 &&
-// RUN: true
+// RUN: clang-cc --emit-llvm -o %t %s
+// RUN: grep "objc_msgSend" %t | count 6
+// RUN: clang-cc -fgnu-runtime --emit-llvm -o %t %s
+// RUN: grep "objc_msg_lookup" %t | count 6
+// RUN: clang-cc -fgnu-runtime -fobjc-nonfragile-abi --emit-llvm -o %t %s
+// RUN: grep "objc_msg_lookup_sender" %t | count 6
typedef struct {
int x;
diff --git a/test/CodeGenObjC/metadata-symbols-32.m b/test/CodeGenObjC/metadata-symbols-32.m
index 8cebe4976e23..288fa8c65a80 100644
--- a/test/CodeGenObjC/metadata-symbols-32.m
+++ b/test/CodeGenObjC/metadata-symbols-32.m
@@ -1,35 +1,34 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s
// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s &&
-// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*section "__OBJC,__category,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CATEGORY_CLASS_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CATEGORY_INSTANCE_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASSEXT_A" = internal global .*section "__OBJC,__class_ext,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*section "__OBJC,__class,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_METHODS_A" = internal global .*section "__OBJC,__cls_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_A" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4' %t &&
+// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*section "__OBJC,__category,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CATEGORY_CLASS_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CATEGORY_INSTANCE_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASSEXT_A" = internal global .*section "__OBJC,__class_ext,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*section "__OBJC,__class,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_METHODS_A" = internal global .*section "__OBJC,__cls_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_A" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4' %t
// Clang's Obj-C 32-bit doesn't emit ivars for the root class.
// RUNX: grep '@"\\01L_OBJC_CLASS_VARIABLES_A" = internal global .*section "__OBJC,__class_vars,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_INSTANCE_METHODS_A" = internal global .*section "__OBJC,__inst_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_INSTANCE_VARIABLES_A" = internal global .*section "__OBJC,__instance_vars,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_PROTOCOL_CLASS_METHODS_P" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_PROTOCOL_INSTANCE_METHODS_P" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_SYMBOLS" = internal global .*section "__OBJC,__symbols,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .*section "__OBJC,__property,regular,no_dead_strip", align 4' %t &&
-// RUN: grep "\.lazy_reference \.objc_class_name_J0" %t &&
-
-// RUN: true
+// RUN: grep '@"\\01L_OBJC_INSTANCE_METHODS_A" = internal global .*section "__OBJC,__inst_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_INSTANCE_VARIABLES_A" = internal global .*section "__OBJC,__instance_vars,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_PROTOCOL_CLASS_METHODS_P" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_PROTOCOL_INSTANCE_METHODS_P" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_SYMBOLS" = internal global .*section "__OBJC,__symbols,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .*section "__OBJC,__property,regular,no_dead_strip", align 4' %t
+// RUN: grep "\.lazy_reference \.objc_class_name_J0" %t
+
/*
diff --git a/test/CodeGenObjC/metadata-symbols-64.m b/test/CodeGenObjC/metadata-symbols-64.m
index bfc4ae9e7546..1bc8be8fbba4 100644
--- a/test/CodeGenObjC/metadata-symbols-64.m
+++ b/test/CodeGenObjC/metadata-symbols-64.m
@@ -1,40 +1,39 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s
// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s &&
-// RUN: grep '@"OBJC_CLASS_$_A" = global' %t &&
-// RUN: grep '@"OBJC_CLASS_$_B" = external global' %t &&
-// RUN: grep '@"OBJC_IVAR_$_A._ivar" = global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_METACLASS_$_A" = global .* section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASSLIST_REFERENCES_$_[0-9]*" = internal global .* section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASSLIST_SUP_REFS_$_[0-9]*" = internal global .* section "__DATA, __objc_superrefs, regular, no_dead_strip", align 8' %t | count 2 &&
-// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_LABEL_CATEGORY_$" = internal global .* section "__DATA, __objc_catlist, regular, no_dead_strip", align 8' %t &&
-// RUN: grep '@"\\01L_OBJC_LABEL_CLASS_$" = internal global .* section "__DATA, __objc_classlist, regular, no_dead_strip", align 8' %t &&
-// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_*" = internal global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"' %t &&
-// RUN: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_CLASS_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_INSTANCE_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_INSTANCE_VARIABLES_A" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_CLASS_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_CLASS_PROTOCOLS_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_CLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global .* section "__DATA, __objc_protolist, coalesced, no_dead_strip", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_METACLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"\\01l_OBJC_PROTOCOL_$_P" = weak hidden global .* section "__DATA,__datacoal_nt,coalesced", align 8' %t &&
-// RUN: grep '@"\\01l_objc_msgSend_fixup_alloc" = weak hidden global .* section "__DATA, __objc_msgrefs, coalesced", align 16' %t &&
-// RUN: grep '@_objc_empty_cache = external global' %t &&
-// RUN: grep '@_objc_empty_vtable = external global' %t &&
-// RUN: grep '@objc_msgSend_fixup(' %t &&
-// RUN: grep '@objc_msgSend_fpret(' %t &&
-
-// RUN: true
+// RUN: grep '@"OBJC_CLASS_$_A" = global' %t
+// RUN: grep '@"OBJC_CLASS_$_B" = external global' %t
+// RUN: grep '@"OBJC_IVAR_$_A._ivar" = global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"OBJC_METACLASS_$_A" = global .* section "__DATA, __objc_data", align 8' %t
+// RUN: grep '@"\\01L_OBJC_CLASSLIST_REFERENCES_$_[0-9]*" = internal global .* section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8' %t
+// RUN: grep '@"\\01L_OBJC_CLASSLIST_SUP_REFS_$_[0-9]*" = internal global .* section "__DATA, __objc_superrefs, regular, no_dead_strip", align 8' %t | count 2
+// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_LABEL_CATEGORY_$" = internal global .* section "__DATA, __objc_catlist, regular, no_dead_strip", align 8' %t
+// RUN: grep '@"\\01L_OBJC_LABEL_CLASS_$" = internal global .* section "__DATA, __objc_classlist, regular, no_dead_strip", align 8' %t
+// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t
+// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_*" = internal global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"' %t
+// RUN: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_CLASS_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_INSTANCE_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_INSTANCE_VARIABLES_A" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_CLASS_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_CLASS_PROTOCOLS_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_CLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global .* section "__DATA, __objc_protolist, coalesced, no_dead_strip", align 8' %t
+// RUN: grep '@"\\01l_OBJC_METACLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t
+// RUN: grep '@"\\01l_OBJC_PROTOCOL_$_P" = weak hidden global .* section "__DATA,__datacoal_nt,coalesced", align 8' %t
+// RUN: grep '@"\\01l_objc_msgSend_fixup_alloc" = weak hidden global .* section "__DATA, __objc_msgrefs, coalesced", align 16' %t
+// RUN: grep '@_objc_empty_cache = external global' %t
+// RUN: grep '@_objc_empty_vtable = external global' %t
+// RUN: grep '@objc_msgSend_fixup(' %t
+// RUN: grep '@objc_msgSend_fpret(' %t
+
/*
diff --git a/test/CodeGenObjC/metadata_symbols.m b/test/CodeGenObjC/metadata_symbols.m
index 1a1d1e1d9810..c608cd402240 100644
--- a/test/CodeGenObjC/metadata_symbols.m
+++ b/test/CodeGenObjC/metadata_symbols.m
@@ -1,26 +1,25 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
-
-// RUN: grep '@"OBJC_METACLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"OBJC_CLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced", align 8' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH3" = global .*section "__DATA,__objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH3"' %t | count 3 &&
-// RUN: grep '@"\\01L_OBJC_CLASS_NAME_" =.*section "__TEXT,__cstring,cstring_literals", align 1' %t | count 1 &&
-// RUN: grep -F 'define internal void @"\01-[A im0]"' %t &&
-// RUN: grep -F 'define internal void @"\01-[A(Cat) im1]"' %t &&
-
-// RUN: clang-cc -fvisibility=hidden -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
-
-// RUN: grep '@"OBJC_METACLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"OBJC_CLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak hidden global .*section "__DATA,__datacoal_nt,coalesced"' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH3" = hidden global .*section "__DATA,__objc_const", align 8' %t &&
-// RUN: grep -F 'define internal void @"\01-[A im0]"' %t &&
-// RUN: grep -F 'define internal void @"\01-[A(Cat) im1]"' %t &&
-
-// RUN: true
+// RUN: clang-cc -fobjc-nonfragile-abi -emit-llvm -o %t %s
+
+// RUN: grep '@"OBJC_METACLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t
+// RUN: grep '@"OBJC_CLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t
+// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced", align 8' %t
+// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t
+// RUN: grep '@"OBJC_EHTYPE_$_EH3" = global .*section "__DATA,__objc_const", align 8' %t
+// RUN: grep '@"OBJC_EHTYPE_$_EH3"' %t | count 3
+// RUN: grep '@"\\01L_OBJC_CLASS_NAME_" =.*section "__TEXT,__cstring,cstring_literals", align 1' %t | count 1
+// RUN: grep -F 'define internal void @"\01-[A im0]"' %t
+// RUN: grep -F 'define internal void @"\01-[A(Cat) im1]"' %t
+
+// RUN: clang-cc -fobjc-nonfragile-abi -fvisibility=hidden -emit-llvm -o %t %s
+
+// RUN: grep '@"OBJC_METACLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t
+// RUN: grep '@"OBJC_CLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t
+// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak hidden global .*section "__DATA,__datacoal_nt,coalesced"' %t
+// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t
+// RUN: grep '@"OBJC_EHTYPE_$_EH3" = hidden global .*section "__DATA,__objc_const", align 8' %t
+// RUN: grep -F 'define internal void @"\01-[A im0]"' %t
+// RUN: grep -F 'define internal void @"\01-[A(Cat) im1]"' %t
+
@interface A
@end
diff --git a/test/CodeGenObjC/missing-atend-metadata.m b/test/CodeGenObjC/missing-atend-metadata.m
new file mode 100644
index 000000000000..664b6f0b16b7
--- /dev/null
+++ b/test/CodeGenObjC/missing-atend-metadata.m
@@ -0,0 +1,24 @@
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck %s
+
+@interface I0
+@end
+
+@implementation I0 // expected-warning {{'@end' is missing in implementation context}}
+- meth { return 0; }
+
+@interface I1 : I0
+@end
+
+@implementation I1 // expected-warning {{'@end' is missing in implementation context}}
+-(void) im0 { self = [super init]; }
+
+@interface I2 : I0
+- I2meth;
+@end
+
+@implementation I2 // expected-warning {{'@end' is missing in implementation context}}
+- I2meth { return 0; }
+
+@implementation I2(CAT) // expected-warning {{'@end' is missing in implementation context}}
+
+// CHECK: @"\01L_OBJC_CLASS_I1" = internal global
diff --git a/test/CodeGenObjC/newproperty-nested-synthesis-1.m b/test/CodeGenObjC/newproperty-nested-synthesis-1.m
index 5196b8244dbb..4d9319839d0b 100644
--- a/test/CodeGenObjC/newproperty-nested-synthesis-1.m
+++ b/test/CodeGenObjC/newproperty-nested-synthesis-1.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
@interface Object
- (id) new;
diff --git a/test/CodeGenObjC/non-lazy-classes.m b/test/CodeGenObjC/non-lazy-classes.m
index 079cc40886f9..367705f26218 100644
--- a/test/CodeGenObjC/non-lazy-classes.m
+++ b/test/CodeGenObjC/non-lazy-classes.m
@@ -1,8 +1,7 @@
// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s &&
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s &&
-// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CLASS_$" = internal global \[1 x .*\] .*@"OBJC_CLASS_$_A".*, section "__DATA, __objc_nlclslist, regular, no_dead_strip", align 8' %t &&
-// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CATEGORY_$" = internal global \[1 x .*\] .*@".01l_OBJC_$_CATEGORY_A_$_Cat".*, section "__DATA, __objc_nlcatlist, regular, no_dead_strip", align 8' %t &&
-// RUN: true
+// RUN: clang-cc -fobjc-nonfragile-abi -emit-llvm -o %t %s
+// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CLASS_$" = internal global \[1 x .*\] .*@"OBJC_CLASS_$_A".*, section "__DATA, __objc_nlclslist, regular, no_dead_strip", align 8' %t
+// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CATEGORY_$" = internal global \[1 x .*\] .*@".01l_OBJC_$_CATEGORY_A_$_Cat".*, section "__DATA, __objc_nlcatlist, regular, no_dead_strip", align 8' %t
@interface A @end
@implementation A
diff --git a/test/CodeGenObjC/objc-align.m b/test/CodeGenObjC/objc-align.m
index eca5959a392a..c029d48ea3a0 100644
--- a/test/CodeGenObjC/objc-align.m
+++ b/test/CodeGenObjC/objc-align.m
@@ -1,16 +1,16 @@
// 32-bit
// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s &&
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*, section "__OBJC,__category,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_C" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_C" = internal global .*, section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_IMAGE_INFO" = internal constant .*, section "__OBJC, __image_info,regular"' %t &&
-// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_METACLASS_C" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*, section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t &&
-// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*, section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t &&
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*, section "__OBJC,__category,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_C" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_C" = internal global .*, section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_IMAGE_INFO" = internal constant .*, section "__OBJC, __image_info,regular"' %t
+// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_METACLASS_C" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*, section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t
+// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*, section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t
// 64-bit
@@ -32,7 +32,6 @@
// RUNX: grep '@"\\01l_OBJC_METACLASS_RO_$_C" = internal global .*, section "__DATA, __objc_const", align 8' %t &&
// RUNX: grep '@"\\01l_OBJC_PROTOCOL_$_P" = weak hidden global .*, section "__DATA,__datacoal_nt,coalesced", align 8' %t &&
-// RUN: true
@interface A @end
@implementation A
diff --git a/test/CodeGenObjC/objc-assign-ivar.m b/test/CodeGenObjC/objc-assign-ivar.m
index f79faaf23826..795dec0d7ea1 100644
--- a/test/CodeGenObjC/objc-assign-ivar.m
+++ b/test/CodeGenObjC/objc-assign-ivar.m
@@ -1,6 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep -F '@objc_assign_ivar' %t | count 14 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep -F '@objc_assign_ivar' %t | count 14
typedef struct {
id element;
diff --git a/test/CodeGenObjC/objc-gc-aggr-assign.m b/test/CodeGenObjC/objc-gc-aggr-assign.m
index 96a9fdf65409..1646cde89202 100644
--- a/test/CodeGenObjC/objc-gc-aggr-assign.m
+++ b/test/CodeGenObjC/objc-gc-aggr-assign.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s &&
+// RUN: clang-cc -fobjc-gc -emit-llvm -o %t %s
// RUN: grep objc_memmove_collectable %t | grep call | count 3
static int count;
diff --git a/test/CodeGenObjC/objc-read-weak-byref.m b/test/CodeGenObjC/objc-read-weak-byref.m
index 7c297be56679..3edaf4c749ed 100644
--- a/test/CodeGenObjC/objc-read-weak-byref.m
+++ b/test/CodeGenObjC/objc-read-weak-byref.m
@@ -1,8 +1,7 @@
-// RUN: clang-cc -fblocks -fobjc-gc -triple x86_64-apple-darwin -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -fblocks -fobjc-gc -triple i386-apple-darwin -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -fblocks -fobjc-gc -triple x86_64-apple-darwin -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -fblocks -fobjc-gc -triple i386-apple-darwin -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
@interface NSObject
- copy;
diff --git a/test/CodeGenObjC/objc2-assign-global.m b/test/CodeGenObjC/objc2-assign-global.m
index 9b6b4151f6a0..6b34796983ff 100644
--- a/test/CodeGenObjC/objc2-assign-global.m
+++ b/test/CodeGenObjC/objc2-assign-global.m
@@ -1,6 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fnext-runtime -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep -F '@objc_assign_global' %t | count 26 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep -F '@objc_assign_global' %t | count 26
@class NSObject;
typedef const struct __CFDictionary * CFDictionaryRef;
diff --git a/test/CodeGenObjC/objc2-ivar-assign.m b/test/CodeGenObjC/objc2-ivar-assign.m
index cfdf87f2f12b..8e9a872f93f3 100644
--- a/test/CodeGenObjC/objc2-ivar-assign.m
+++ b/test/CodeGenObjC/objc2-ivar-assign.m
@@ -1,6 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep objc_assign_ivar %t | count 6 &&
-// RUN: true
+// RUN: clang-cc -fobjc-nonfragile-abi -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep objc_assign_ivar %t | count 6
@interface I @end
diff --git a/test/CodeGenObjC/objc2-new-gc-api-strongcast.m b/test/CodeGenObjC/objc2-new-gc-api-strongcast.m
index 6a1aea6a7340..b6a0c03ac35b 100644
--- a/test/CodeGenObjC/objc2-new-gc-api-strongcast.m
+++ b/test/CodeGenObjC/objc2-new-gc-api-strongcast.m
@@ -1,6 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fblocks -fnext-runtime -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep -F '@objc_assign_strongCast' %t | count 4 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fblocks -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep -F '@objc_assign_strongCast' %t | count 4
@interface DSATextSearch @end
diff --git a/test/CodeGenObjC/objc2-no-write-barrier.m b/test/CodeGenObjC/objc2-no-write-barrier.m
index 2c5350969416..b41f63fe4528 100644
--- a/test/CodeGenObjC/objc2-no-write-barrier.m
+++ b/test/CodeGenObjC/objc2-no-write-barrier.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s
// RUN: grep 'objc_assign' %t | count 0
typedef struct {
diff --git a/test/CodeGenObjC/objc2-property-encode.m b/test/CodeGenObjC/objc2-property-encode.m
index 2bff2fc1a4ed..f1c1024cece5 100644
--- a/test/CodeGenObjC/objc2-property-encode.m
+++ b/test/CodeGenObjC/objc2-property-encode.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -emit-llvm -o %t %s
// RUN: grep -e "T@\\\\22NSString\\\\22" %t
@interface NSString @end
diff --git a/test/CodeGenObjC/objc2-protocol-enc.m b/test/CodeGenObjC/objc2-protocol-enc.m
index 559b0b8c76a0..2174792bd920 100644
--- a/test/CodeGenObjC/objc2-protocol-enc.m
+++ b/test/CodeGenObjC/objc2-protocol-enc.m
@@ -1,7 +1,7 @@
-// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep -e "T@\\\22<X>\\\22" %t &&
-// RUN: grep -e "T@\\\22<X><Y>\\\22" %t &&
-// RUN: grep -e "T@\\\22<X><Y><Z>\\\22" %t &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -emit-llvm -o %t %s
+// RUN: grep -e "T@\\\22<X>\\\22" %t
+// RUN: grep -e "T@\\\22<X><Y>\\\22" %t
+// RUN: grep -e "T@\\\22<X><Y><Z>\\\22" %t
// RUN: grep -e "T@\\\22Foo<X><Y><Z>\\\22" %t
@protocol X, Y, Z;
diff --git a/test/CodeGenObjC/objc2-strong-cast.m b/test/CodeGenObjC/objc2-strong-cast.m
index d0fcb6ced928..73fe16af4f73 100644
--- a/test/CodeGenObjC/objc2-strong-cast.m
+++ b/test/CodeGenObjC/objc2-strong-cast.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s
+// RUN: clang-cc -fobjc-gc -emit-llvm -o %t %s
@interface I {
__attribute__((objc_gc(strong))) signed long *_documentIDs;
diff --git a/test/CodeGenObjC/objc2-weak-assign.m b/test/CodeGenObjC/objc2-weak-assign.m
index 635ca38df46c..ea53b020124c 100644
--- a/test/CodeGenObjC/objc2-weak-assign.m
+++ b/test/CodeGenObjC/objc2-weak-assign.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s
// RUN: grep -e "objc_assign_weak" %t | grep -e "call" | count 6
__weak id* x;
diff --git a/test/CodeGenObjC/objc2-weak-compare.m b/test/CodeGenObjC/objc2-weak-compare.m
index be769899a17d..82cc558b567b 100644
--- a/test/CodeGenObjC/objc2-weak-compare.m
+++ b/test/CodeGenObjC/objc2-weak-compare.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -fobjc-gc -emit-llvm -o %t %s
+// RUN: clang-cc -triple i386-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s
@interface PBXTarget
{
diff --git a/test/CodeGenObjC/objc2-weak-import-attribute.m b/test/CodeGenObjC/objc2-weak-import-attribute.m
new file mode 100644
index 000000000000..4a5f14e2e0f7
--- /dev/null
+++ b/test/CodeGenObjC/objc2-weak-import-attribute.m
@@ -0,0 +1,34 @@
+// RUN: clang-cc -fobjc-nonfragile-abi -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-64 %s
+
+__attribute__((weak_import)) @interface WeakClass
+@end
+
+@interface MySubclass : WeakClass @end
+
+@implementation MySubclass @end
+
+@implementation WeakClass(MyCategory) @end
+
+
+__attribute__((weak_import))
+@interface WeakClass1 @end
+
+@implementation WeakClass1(MyCategory) @end
+
+@implementation WeakClass1(YourCategory) @end
+
+ __attribute__((weak_import))
+@interface WeakClass3
++ message;
+@end
+
+int main() {
+ [WeakClass3 message];
+}
+
+// CHECK-X86-64: OBJC_METACLASS_$_WeakClass" = extern_weak global
+// CHECK-X86-64: OBJC_CLASS_$_WeakClass" = extern_weak global
+// CHECK-X86-64: OBJC_CLASS_$_WeakClass1" = extern_weak global
+// CHECK-X86-64: OBJC_CLASS_$_WeakClass3" = extern_weak global
+
+
diff --git a/test/CodeGenObjC/objc2-weak-ivar-debug.m b/test/CodeGenObjC/objc2-weak-ivar-debug.m
index 24a7757b9acf..3930989f44df 100644
--- a/test/CodeGenObjC/objc2-weak-ivar-debug.m
+++ b/test/CodeGenObjC/objc2-weak-ivar-debug.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -g -emit-llvm -o - %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -g -emit-llvm -o - %s
// RUN: clang-cc -triple i386-apple-darwin9 -fobjc-gc -g -emit-llvm -o - %s
// rdar://7252252
diff --git a/test/CodeGenObjC/objc2-write-barrier-2.m b/test/CodeGenObjC/objc2-write-barrier-2.m
index c47224f1c516..cdb135f0150c 100644
--- a/test/CodeGenObjC/objc2-write-barrier-2.m
+++ b/test/CodeGenObjC/objc2-write-barrier-2.m
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fnext-runtime -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep -F '@objc_assign_global' %t | count 7 &&
-// RUN: grep -F '@objc_assign_ivar' %t | count 5 &&
-// RUN: grep -F '@objc_assign_strongCast' %t | count 8 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep -F '@objc_assign_global' %t | count 7
+// RUN: grep -F '@objc_assign_ivar' %t | count 5
+// RUN: grep -F '@objc_assign_strongCast' %t | count 8
extern id **somefunc(void);
extern id *somefunc2(void);
diff --git a/test/CodeGenObjC/objc2-write-barrier-3.m b/test/CodeGenObjC/objc2-write-barrier-3.m
index 2fb416b79b2f..7058302f98a8 100644
--- a/test/CodeGenObjC/objc2-write-barrier-3.m
+++ b/test/CodeGenObjC/objc2-write-barrier-3.m
@@ -1,7 +1,6 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep objc_assign_ivar %t | count 3 &&
-// RUN: grep objc_assign_strongCast %t | count 6 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep objc_assign_ivar %t | count 3
+// RUN: grep objc_assign_strongCast %t | count 6
struct Slice {
void *__strong * items;
diff --git a/test/CodeGenObjC/objc2-write-barrier-4.m b/test/CodeGenObjC/objc2-write-barrier-4.m
index f96a233787b0..4c863f4a7639 100644
--- a/test/CodeGenObjC/objc2-write-barrier-4.m
+++ b/test/CodeGenObjC/objc2-write-barrier-4.m
@@ -1,7 +1,6 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep objc_assign_global %t | count 3 &&
-// RUN: grep objc_assign_strongCast %t | count 2 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep objc_assign_global %t | count 3
+// RUN: grep objc_assign_strongCast %t | count 2
@interface A
@end
diff --git a/test/CodeGenObjC/objc2-write-barrier-5.m b/test/CodeGenObjC/objc2-write-barrier-5.m
index 5b8f02cc1e16..2e51b44093a3 100644
--- a/test/CodeGenObjC/objc2-write-barrier-5.m
+++ b/test/CodeGenObjC/objc2-write-barrier-5.m
@@ -1,7 +1,6 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep objc_assign_ivar %t | count 0 &&
-// RUN: grep objc_assign_strongCast %t | count 5 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep objc_assign_ivar %t | count 0
+// RUN: grep objc_assign_strongCast %t | count 5
@interface TestUnarchiver
{
diff --git a/test/CodeGenObjC/objc2-write-barrier.m b/test/CodeGenObjC/objc2-write-barrier.m
index 53fa10a7a75f..bff6d8fdd012 100644
--- a/test/CodeGenObjC/objc2-write-barrier.m
+++ b/test/CodeGenObjC/objc2-write-barrier.m
@@ -1,7 +1,6 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -fnext-runtime -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep -F '@objc_assign_global' %t | count 21 &&
-// RUN: grep -F '@objc_assign_ivar' %t | count 11 &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
+// RUN: grep -F '@objc_assign_global' %t | count 21
+// RUN: grep -F '@objc_assign_ivar' %t | count 11
typedef const struct __CFDictionary * CFDictionaryRef;
diff --git a/test/CodeGenObjC/object-incr-decr-1.m b/test/CodeGenObjC/object-incr-decr-1.m
index 53311f7aa18c..25b969886023 100644
--- a/test/CodeGenObjC/object-incr-decr-1.m
+++ b/test/CodeGenObjC/object-incr-decr-1.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -emit-llvm %s -o %t
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm %s -o %t
@interface Foo
{
diff --git a/test/CodeGenObjC/overloadable.m b/test/CodeGenObjC/overloadable.m
index 7e9cc3d3b36d..bd3aff81b97d 100644
--- a/test/CodeGenObjC/overloadable.m
+++ b/test/CodeGenObjC/overloadable.m
@@ -1,9 +1,9 @@
// rdar://6657613
-// RUN: clang-cc -emit-llvm %s -o %t &&
+// RUN: clang-cc -emit-llvm %s -o %t
@class C;
-// RUN: grep _Z1fP11objc_object %t | count 1 &&
+// RUN: grep _Z1fP11objc_object %t | count 1
void __attribute__((overloadable)) f(id c) { }
// RUN: grep _Z1fP1C %t | count 1
diff --git a/test/CodeGenObjC/property-aggr-type.m b/test/CodeGenObjC/property-aggr-type.m
index 0cb7a5e2f40a..e2890b6ee80e 100644
--- a/test/CodeGenObjC/property-aggr-type.m
+++ b/test/CodeGenObjC/property-aggr-type.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
@interface Object
- (id) new;
diff --git a/test/CodeGenObjC/property-agrr-getter.m b/test/CodeGenObjC/property-agrr-getter.m
index 46205796936f..e25429ed7525 100644
--- a/test/CodeGenObjC/property-agrr-getter.m
+++ b/test/CodeGenObjC/property-agrr-getter.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
typedef struct {
unsigned f0;
diff --git a/test/CodeGenObjC/property-complex.m b/test/CodeGenObjC/property-complex.m
index 2e23ca410559..aedb1fac6c2f 100644
--- a/test/CodeGenObjC/property-complex.m
+++ b/test/CodeGenObjC/property-complex.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -S -o - %s &&
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -S -o - %s
// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -S -o - %s
@interface I0 {
diff --git a/test/CodeGenObjC/property-getter-dot-syntax.m b/test/CodeGenObjC/property-getter-dot-syntax.m
index d98e9bab6da9..c1cc5e994774 100644
--- a/test/CodeGenObjC/property-getter-dot-syntax.m
+++ b/test/CodeGenObjC/property-getter-dot-syntax.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
@protocol NSObject
- (void *)description;
diff --git a/test/CodeGenObjC/property-incr-decr-1.m b/test/CodeGenObjC/property-incr-decr-1.m
index 772e872a214f..eb227dde19d5 100644
--- a/test/CodeGenObjC/property-incr-decr-1.m
+++ b/test/CodeGenObjC/property-incr-decr-1.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
@interface Object
- (id) new;
diff --git a/test/CodeGenObjC/property-setter-attr.m b/test/CodeGenObjC/property-setter-attr.m
index 5f0edf8271e7..390392415d73 100644
--- a/test/CodeGenObjC/property-setter-attr.m
+++ b/test/CodeGenObjC/property-setter-attr.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin8 -o %t %s &&
+// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin8 -o %t %s
// RUN: grep -e "SiSetOtherThings:" %t
@interface A
diff --git a/test/CodeGenObjC/property.m b/test/CodeGenObjC/property.m
index 264adf1106e2..59f096f5c590 100644
--- a/test/CodeGenObjC/property.m
+++ b/test/CodeGenObjC/property.m
@@ -1,6 +1,6 @@
-// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
+// RUN: clang-cc --emit-llvm -o %t %s
-#include <stdio.h>
+int printf(const char *, ...);
@interface Root
-(id) alloc;
diff --git a/test/CodeGenObjC/protocol-in-extended-class.m b/test/CodeGenObjC/protocol-in-extended-class.m
index 87bda46faeaa..cad59b0fcdb9 100644
--- a/test/CodeGenObjC/protocol-in-extended-class.m
+++ b/test/CodeGenObjC/protocol-in-extended-class.m
@@ -1,8 +1,7 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -S %s -o %t-64.s &&
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
-// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s &&
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
-// RUN: true
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
@protocol MyProtocol
@end
diff --git a/test/CodeGenObjC/protocol-property-synth.m b/test/CodeGenObjC/protocol-property-synth.m
index e91f3552310d..ab230af23211 100644
--- a/test/CodeGenObjC/protocol-property-synth.m
+++ b/test/CodeGenObjC/protocol-property-synth.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s
+// RUN: clang-cc -fobjc-nonfragile-abi -emit-llvm -o %t %s
@interface BaseClass {
id _delegate;
diff --git a/test/CodeGenObjC/protocols-lazy.m b/test/CodeGenObjC/protocols-lazy.m
index a8f79026f780..54ca19ceb46a 100644
--- a/test/CodeGenObjC/protocols-lazy.m
+++ b/test/CodeGenObjC/protocols-lazy.m
@@ -1,36 +1,36 @@
-// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin8 -o %t %s &&
+// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin8 -o %t %s
// RUNX: llvm-gcc -S -emit-llvm -o %t %s &&
// No object generated
-// RUN: grep OBJC_PROTOCOL_P0 %t | count 0 &&
+// RUN: grep OBJC_PROTOCOL_P0 %t | count 0
@protocol P0;
// No object generated
-// RUN: grep OBJC_PROTOCOL_P1 %t | count 0 &&
+// RUN: grep OBJC_PROTOCOL_P1 %t | count 0
@protocol P1 -im1; @end
// Definition triggered by protocol reference.
-// RUN: grep OBJC_PROTOCOL_P2 %t | count 3 &&
-// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P2 %t | count 3 &&
+// RUN: grep OBJC_PROTOCOL_P2 %t | count 3
+// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P2 %t | count 3
@protocol P2 -im1; @end
void f0() { id x = @protocol(P2); }
// Forward definition triggered by protocol reference.
-// RUN: grep OBJC_PROTOCOL_P3 %t | count 3 &&
-// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P3 %t | count 0 &&
+// RUN: grep OBJC_PROTOCOL_P3 %t | count 3
+// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P3 %t | count 0
@protocol P3;
void f1() { id x = @protocol(P3); }
// Definition triggered by class reference.
-// RUN: grep OBJC_PROTOCOL_P4 %t | count 3 &&
-// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P4 %t | count 3 &&
+// RUN: grep OBJC_PROTOCOL_P4 %t | count 3
+// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P4 %t | count 3
@protocol P4 -im1; @end
@interface I0<P4> @end
@implementation I0 -im1 { return 0; }; @end
// Definition following forward reference.
-// RUN: grep OBJC_PROTOCOL_P5 %t | count 3 &&
-// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P5 %t | count 3 &&
+// RUN: grep OBJC_PROTOCOL_P5 %t | count 3
+// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P5 %t | count 3
@protocol P5;
void f2() { id x = @protocol(P5); } // This generates a forward
// reference, which has to be
@@ -38,11 +38,10 @@ void f2() { id x = @protocol(P5); } // This generates a forward
@protocol P5 -im1; @end
// Protocol reference following definition.
-// RUN: grep OBJC_PROTOCOL_P6 %t | count 4 &&
-// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P6 %t | count 3 &&
+// RUN: grep OBJC_PROTOCOL_P6 %t | count 4
+// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P6 %t | count 3
@protocol P6 -im1; @end
@interface I1<P6> @end
@implementation I1 -im1 { return 0; }; @end
void f3() { id x = @protocol(P6); }
-// RUN: true
diff --git a/test/CodeGenObjC/protocols.m b/test/CodeGenObjC/protocols.m
index 4cfb83bf00e0..c510685e521d 100644
--- a/test/CodeGenObjC/protocols.m
+++ b/test/CodeGenObjC/protocols.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm %s -o %t
+// RUN: clang-cc -emit-llvm %s -o %t
void p(const char*, ...);
diff --git a/test/CodeGenObjC/runtime-fns.m b/test/CodeGenObjC/runtime-fns.m
index 0d8570799902..3c6894dddd17 100644
--- a/test/CodeGenObjC/runtime-fns.m
+++ b/test/CodeGenObjC/runtime-fns.m
@@ -1,6 +1,6 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep -e "^de.*objc_msgSend[0-9]*(" %t | count 1 &&
-// RUN: clang-cc -DWITHDEF -fnext-runtime -emit-llvm -o %t %s &&
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: grep -e "^de.*objc_msgSend[0-9]*(" %t | count 1
+// RUN: clang-cc -DWITHDEF -emit-llvm -o %t %s
// RUN: grep -e "^de.*objc_msgSend[0-9]*(" %t | count 1
id objc_msgSend(int x);
diff --git a/test/CodeGenObjC/super-classmethod-category.m b/test/CodeGenObjC/super-classmethod-category.m
index 27cdbf6aed41..033bc972a348 100644
--- a/test/CodeGenObjC/super-classmethod-category.m
+++ b/test/CodeGenObjC/super-classmethod-category.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
@interface SUPER
+ (void)Meth;
diff --git a/test/CodeGenObjC/super-message-fragileabi.m b/test/CodeGenObjC/super-message-fragileabi.m
new file mode 100644
index 000000000000..edc26a1157fd
--- /dev/null
+++ b/test/CodeGenObjC/super-message-fragileabi.m
@@ -0,0 +1,32 @@
+// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck %s
+
+@class Some;
+
+@protocol Proto
+- (id)initSome:(Some *)anArg;
+@end
+
+
+@interface Table <Proto>
+@end
+
+@interface BetterTable: Table
+
+- (id)initSome:(Some *)arg;
+
+@end
+
+@implementation BetterTable
+
+- (id)initSome:(Some *)arg {
+
+ if(self=[super initSome:arg])
+ {
+ ;
+ }
+// CHECK: load %struct._objc_class** getelementptr inbounds (%struct._objc_class* @"\01L_OBJC_CLASS_BetterTable", i32 0, i32 1)
+
+ return self;
+}
+@end
+
diff --git a/test/CodeGenObjC/synchronized.m b/test/CodeGenObjC/synchronized.m
index b398ca6c0a59..8147cd1e235f 100644
--- a/test/CodeGenObjC/synchronized.m
+++ b/test/CodeGenObjC/synchronized.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin9 -o %t %s -O2 &&
-// RUN: grep 'ret i32' %t | count 1 &&
+// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin9 -o %t %s -O2
+// RUN: grep 'ret i32' %t | count 1
// RUN: grep 'ret i32 1' %t | count 1
@interface MyClass
diff --git a/test/CodeGenObjC/synthesize_ivar-cont-class.m b/test/CodeGenObjC/synthesize_ivar-cont-class.m
index b1a7d0e68030..dd444c358b7e 100644
--- a/test/CodeGenObjC/synthesize_ivar-cont-class.m
+++ b/test/CodeGenObjC/synthesize_ivar-cont-class.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s &&
+// RUN: clang-cc -fobjc-nonfragile-abi -emit-llvm -o %t %s
// RUN: grep '@"OBJC_IVAR_$_XCOrganizerDeviceNodeInfo.viewController"' %t
@interface XCOrganizerNodeInfo
diff --git a/test/CodeGenObjC/synthesize_ivar.m b/test/CodeGenObjC/synthesize_ivar.m
index e1746f1da136..9ed08d9ce559 100644
--- a/test/CodeGenObjC/synthesize_ivar.m
+++ b/test/CodeGenObjC/synthesize_ivar.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s
+// RUN: clang-cc -fobjc-nonfragile-abi -emit-llvm -o %t %s
@interface I
@property int IP;
diff --git a/test/CodeGenObjC/try.m b/test/CodeGenObjC/try.m
index 7701b23e0819..eebc482e4608 100644
--- a/test/CodeGenObjC/try.m
+++ b/test/CodeGenObjC/try.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -S -o - -triple=i686-apple-darwin9 &&
+// RUN: clang-cc %s -S -o - -triple=i686-apple-darwin9
// RUN: clang-cc %s -S -o - -triple=x86_64-apple-darwin9
// rdar://6757213 - Don't crash if the internal proto for
diff --git a/test/CodeGenObjC/unname-bf-metadata.m b/test/CodeGenObjC/unname-bf-metadata.m
index a7636e4ebc8b..605d09b03322 100644
--- a/test/CodeGenObjC/unname-bf-metadata.m
+++ b/test/CodeGenObjC/unname-bf-metadata.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
// Test that meta-data for ivar lists with unnamed bitfield are generated.
//
@interface Foo {
diff --git a/test/CodeGenObjC/variadic-sends.m b/test/CodeGenObjC/variadic-sends.m
index 8697feec5d6d..e2d13e3ae41d 100644
--- a/test/CodeGenObjC/variadic-sends.m
+++ b/test/CodeGenObjC/variadic-sends.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-unknown-unknown -fnext-runtime -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-32 %s &&
-// RUN: clang-cc -triple x86_64-unknown-unknown -fnext-runtime -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-64 %s
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-32 %s
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-64 %s
@interface A
-(void) im0;
diff --git a/test/Coverage/ast-printing.c b/test/Coverage/ast-printing.c
index efa950934ba0..2bed12e60bea 100644
--- a/test/Coverage/ast-printing.c
+++ b/test/Coverage/ast-printing.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc --fsyntax-only %s &&
-// RUN: clang-cc --ast-print %s &&
-// RUN: clang-cc --ast-dump %s &&
+// RUN: clang-cc --fsyntax-only %s
+// RUN: clang-cc --ast-print %s
+// RUN: clang-cc --ast-dump %s
// RUN: clang-cc --ast-print-xml -o %t %s
#include "c-language-features.inc"
diff --git a/test/Coverage/ast-printing.cpp b/test/Coverage/ast-printing.cpp
index 10d01c743744..93c71912f64c 100644
--- a/test/Coverage/ast-printing.cpp
+++ b/test/Coverage/ast-printing.cpp
@@ -1,5 +1,5 @@
-// RUN: clang-cc --fsyntax-only %s &&
-// RUN: clang-cc --ast-print %s &&
+// RUN: clang-cc --fsyntax-only %s
+// RUN: clang-cc --ast-print %s
// RUN: clang-cc --ast-dump %s
// FIXME: clang-cc --ast-print-xml -o %t %s
diff --git a/test/Coverage/ast-printing.m b/test/Coverage/ast-printing.m
index 85bbd4314a4d..e7589b80ed81 100644
--- a/test/Coverage/ast-printing.m
+++ b/test/Coverage/ast-printing.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc --fsyntax-only %s &&
-// RUN: clang-cc --ast-print %s &&
+// RUN: clang-cc --fsyntax-only %s
+// RUN: clang-cc --ast-print %s
// RUN: clang-cc --ast-dump %s
#include "objc-language-features.inc"
diff --git a/test/Coverage/codegen-next.m b/test/Coverage/codegen-next.m
index bca83cba6931..f211a5914e55 100644
--- a/test/Coverage/codegen-next.m
+++ b/test/Coverage/codegen-next.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -emit-llvm -o %t %s
+// RUN: clang-cc -g -emit-llvm -o %t %s
#include "objc-language-features.inc"
diff --git a/test/Coverage/codegen.c b/test/Coverage/codegen.c
index 543c361e1bbd..f1d7fcc88672 100644
--- a/test/Coverage/codegen.c
+++ b/test/Coverage/codegen.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm-bc -o %t %s &&
-// RUN: clang-cc -triple i386-unknown-unknown -g -emit-llvm-bc -o %t %s &&
-// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm-bc -o %t %s &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm-bc -o %t %s
+// RUN: clang-cc -triple i386-unknown-unknown -g -emit-llvm-bc -o %t %s
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm-bc -o %t %s
// RUN: clang-cc -triple x86_64-unknown-unknown -g -emit-llvm-bc -o %t %s
#include "c-language-features.inc"
diff --git a/test/Coverage/html-diagnostics.c b/test/Coverage/html-diagnostics.c
index 55376d0e440e..3079632e1205 100644
--- a/test/Coverage/html-diagnostics.c
+++ b/test/Coverage/html-diagnostics.c
@@ -1,5 +1,5 @@
-// RUN: rm -rf %t &&
-// RUN: clang-cc -analyze -analyzer-output=html -checker-cfref -o %t %s &&
+// RUN: rm -rf %t
+// RUN: clang-cc -analyze -analyzer-output=html -checker-cfref -o %t %s
// RUN: cat %t/*.html | FileCheck %s
// CHECK: <h3>Annotated Source Code</h3>
diff --git a/test/Coverage/parse-callbacks.c b/test/Coverage/parse-callbacks.c
index 309074de9e7d..537d63037441 100644
--- a/test/Coverage/parse-callbacks.c
+++ b/test/Coverage/parse-callbacks.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc --parse-noop %s &&
+// RUN: clang-cc --parse-noop %s
// RUN: clang-cc --parse-print-callbacks %s
#include "c-language-features.inc"
diff --git a/test/Coverage/parse-callbacks.m b/test/Coverage/parse-callbacks.m
index dc1dcfc66270..fc240cfef721 100644
--- a/test/Coverage/parse-callbacks.m
+++ b/test/Coverage/parse-callbacks.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc --parse-noop %s &&
+// RUN: clang-cc --parse-noop %s
// RUN: clang-cc --parse-print-callbacks %s
#include "objc-language-features.inc"
diff --git a/test/Coverage/targets.c b/test/Coverage/targets.c
index c4f030fff3d0..23990e06d393 100644
--- a/test/Coverage/targets.c
+++ b/test/Coverage/targets.c
@@ -1,23 +1,22 @@
-// RUN: clang-cc -g -triple armv6-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple armv6-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple bfin-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple i686-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple i686-pc-linux-gnu -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple i686-unknown-dragonfly -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple i686-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple i686-unknown-win32 -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple pic16-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple powerpc-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple powerpc-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple powerpc64-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple powerpc64-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple sparc-unknown-solaris -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple sparc-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple x86_64-pc-linux-gnu -emit-llvm -o %t %s &&
-// RUN: clang-cc -g -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
+// RUN: clang-cc -g -triple armv6-apple-darwin9 -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple armv6-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple bfin-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple i686-apple-darwin9 -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple i686-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple i686-unknown-dragonfly -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple i686-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple i686-unknown-win32 -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple pic16-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple powerpc-apple-darwin9 -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple powerpc-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple powerpc64-apple-darwin9 -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple powerpc64-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple sparc-unknown-solaris -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple sparc-unknown-unknown -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple x86_64-apple-darwin9 -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple x86_64-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: clang-cc -g -triple x86_64-unknown-unknown -emit-llvm -o %t %s
// <rdar://problem/7181838> clang 1.0 fails to compile Python 2.6
-// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -mmacosx-version-min=10.4 &&
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -mmacosx-version-min=10.4
-// RUN: true
diff --git a/test/Driver/Xarch.c b/test/Driver/Xarch.c
index a2a3fdea309e..ba6f5c63d4d4 100644
--- a/test/Driver/Xarch.c
+++ b/test/Driver/Xarch.c
@@ -1,10 +1,9 @@
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -m32 -Xarch_i386 -O2 %s -S -### 2> %t.log &&
-// RUN: grep ' "-O2" ' %t.log | count 1 &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -m64 -Xarch_i386 -O2 %s -S -### 2> %t.log &&
-// RUN: grep ' "-O2" ' %t.log | count 0 &&
-// RUN: grep "argument unused during compilation: '-Xarch_i386 -O2'" %t.log &&
-// RUN: not clang -ccc-host-triple i386-apple-darwin9 -m32 -Xarch_i386 -o -Xarch_i386 -S %s -S -Xarch_i386 -o 2> %t.log &&
-// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -o'" %t.log | count 2 &&
-// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -S'" %t.log &&
-// RUN: true
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -m32 -Xarch_i386 -O2 %s -S -### 2> %t.log
+// RUN: grep ' "-O2" ' %t.log | count 1
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -m64 -Xarch_i386 -O2 %s -S -### 2> %t.log
+// RUN: grep ' "-O2" ' %t.log | count 0
+// RUN: grep "argument unused during compilation: '-Xarch_i386 -O2'" %t.log
+// RUN: not clang -ccc-host-triple i386-apple-darwin9 -m32 -Xarch_i386 -o -Xarch_i386 -S %s -S -Xarch_i386 -o 2> %t.log
+// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -o'" %t.log | count 2
+// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -S'" %t.log
diff --git a/test/Driver/analyze.c b/test/Driver/analyze.c
index 03810688d1f7..ff35cc57f1c0 100644
--- a/test/Driver/analyze.c
+++ b/test/Driver/analyze.c
@@ -1,7 +1,7 @@
// Verify that the analyzer gets the same flags as normal compilation
// (at least for a few key ones).
-// RUN: env MACOSX_DEPLOYMENT_TARGET=10.5 clang -ccc-host-triple i386-apple-darwin9 -### --analyze -o /dev/null %s -msse 2> %t.log &&
+// RUN: env MACOSX_DEPLOYMENT_TARGET=10.5 clang -ccc-host-triple i386-apple-darwin9 -### --analyze -o /dev/null %s -msse 2> %t.log
// RUN: FileCheck --input-file=%t.log %s
// CHECK: "-analyze"
diff --git a/test/Driver/arm-darwin-builtin.c b/test/Driver/arm-darwin-builtin.c
index 5da8074ee3a7..63cf34332ae1 100644
--- a/test/Driver/arm-darwin-builtin.c
+++ b/test/Driver/arm-darwin-builtin.c
@@ -8,7 +8,7 @@
// RUX: not grep -- "-fno-builtin-strcat" %t &&
// RUX: not grep -- "-fno-builtin-strcpy" %t &&
-// RUN: clang -ccc-no-clang -ccc-host-triple x86_64-apple-darwin9 -arch arm -### -fsyntax-only %s -fbuiltin-strcat -fbuiltin-strcpy 2> %t &&
-// RUN: not grep -- "-fno-builtin-strcat" %t &&
+// RUN: clang -ccc-no-clang -ccc-host-triple x86_64-apple-darwin9 -arch arm -### -fsyntax-only %s -fbuiltin-strcat -fbuiltin-strcpy 2> %t
+// RUN: not grep -- "-fno-builtin-strcat" %t
// RUN: not grep -- "-fno-builtin-strcpy" %t
diff --git a/test/Driver/ast.c b/test/Driver/ast.c
index 814b597bb19f..fd38c108b051 100644
--- a/test/Driver/ast.c
+++ b/test/Driver/ast.c
@@ -1,6 +1,6 @@
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -emit-ast %s 2> %t &&
-// RUN: echo 'END' >> %t &&
-// RUN: FileCheck -check-prefix EMIT-AST-PHASES -input-file %t %s &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -emit-ast %s 2> %t
+// RUN: echo 'END' >> %t
+// RUN: FileCheck -check-prefix EMIT-AST-PHASES -input-file %t %s
// EMIT-AST-PHASES: 0: input,
// EMIT-AST-PHASES: , c
@@ -9,9 +9,9 @@
// EMIT-AST-PHASES-NOT: 3:
// EMIT-AST-PHASES: END
-// RUN: touch %t.ast &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -c %t.ast 2> %t &&
-// RUN: echo 'END' >> %t &&
+// RUN: touch %t.ast
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -c %t.ast 2> %t
+// RUN: echo 'END' >> %t
// RUN: FileCheck -check-prefix COMPILE-AST-PHASES -input-file %t %s
// COMPILE-AST-PHASES: 0: input,
diff --git a/test/Driver/bindings.c b/test/Driver/bindings.c
index 393739006bb7..41d6a7ced175 100644
--- a/test/Driver/bindings.c
+++ b/test/Driver/bindings.c
@@ -1,56 +1,55 @@
// Basic binding.
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings %s 2> %t &&
-// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: ".*\.s"' %t &&
-// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t &&
-// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t &&
-
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang %s 2> %t &&
-// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: ".*\.s"' %t &&
-// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t &&
-// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t &&
-
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -no-integrated-cpp %s 2> %t &&
-// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: ".*\.i"' %t &&
-// RUN: grep '"gcc::Compile", inputs: \[".*\.i"\], output: ".*\.s"' %t &&
-// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t &&
-// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t &&
-
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -no-integrated-cpp -pipe %s 2> %t &&
-// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: (pipe)' %t &&
-// RUN: grep '"gcc::Compile", inputs: \[(pipe)\], output: (pipe)' %t &&
-// RUN: grep '"gcc::Assemble", inputs: \[(pipe)\], output: ".*\.o"' %t &&
-// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t &&
-
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -x c-header %s 2> %t &&
-// RUN: grep '"gcc::Precompile", inputs: \[".*bindings.c"\], output: ".*bindings.c.gch' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings %s 2> %t
+// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: ".*\.s"' %t
+// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t
+// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t
+
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang %s 2> %t
+// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: ".*\.s"' %t
+// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t
+// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t
+
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -no-integrated-cpp %s 2> %t
+// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: ".*\.i"' %t
+// RUN: grep '"gcc::Compile", inputs: \[".*\.i"\], output: ".*\.s"' %t
+// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t
+// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t
+
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -no-integrated-cpp -pipe %s 2> %t
+// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: (pipe)' %t
+// RUN: grep '"gcc::Compile", inputs: \[(pipe)\], output: (pipe)' %t
+// RUN: grep '"gcc::Assemble", inputs: \[(pipe)\], output: ".*\.o"' %t
+// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t
+
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -x c-header %s 2> %t
+// RUN: grep '"gcc::Precompile", inputs: \[".*bindings.c"\], output: ".*bindings.c.gch' %t
// Clang control options
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -fsyntax-only %s 2> %t &&
-// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: (nothing)' %t &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -fsyntax-only %s 2> %t &&
-// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: (nothing)' %t &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang-cxx -fsyntax-only -x c++ %s 2> %t &&
-// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: (nothing)' %t &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-clang-cxx -fsyntax-only -x c++ %s 2> %t &&
-// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: (nothing)' %t &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang-cpp -fsyntax-only -no-integrated-cpp %s 2> %t &&
-// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: ".*\.i"' %t &&
-// RUN: grep '"clang", inputs: \[".*\.i"\], output: (nothing)' %t &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings -ccc-clang-archs i386 %s -S -arch ppc 2> %t &&
-// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: "bindings.s"' %t &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings -ccc-clang-archs powerpc %s -S -arch ppc 2> %t &&
-// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: "bindings.s"' %t &&
-
-// RUN: clang -ccc-host-triple powerpc-unknown-unknown -ccc-print-bindings -ccc-clang-archs "" %s -S 2> %t &&
-// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: "bindings.s"' %t &&
-// RUN: clang -ccc-host-triple powerpc-unknown-unknown -ccc-print-bindings -ccc-clang-archs "i386" %s -S 2> %t &&
-// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: "bindings.s"' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -fsyntax-only %s 2> %t
+// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: (nothing)' %t
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -fsyntax-only %s 2> %t
+// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: (nothing)' %t
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang-cxx -fsyntax-only -x c++ %s 2> %t
+// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: (nothing)' %t
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-clang-cxx -fsyntax-only -x c++ %s 2> %t
+// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: (nothing)' %t
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang-cpp -fsyntax-only -no-integrated-cpp %s 2> %t
+// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: ".*\.i"' %t
+// RUN: grep '"clang", inputs: \[".*\.i"\], output: (nothing)' %t
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings -ccc-clang-archs i386 %s -S -arch ppc 2> %t
+// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: "bindings.s"' %t
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings -ccc-clang-archs powerpc %s -S -arch ppc 2> %t
+// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: "bindings.s"' %t
+
+// RUN: clang -ccc-host-triple powerpc-unknown-unknown -ccc-print-bindings -ccc-clang-archs "" %s -S 2> %t
+// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: "bindings.s"' %t
+// RUN: clang -ccc-host-triple powerpc-unknown-unknown -ccc-print-bindings -ccc-clang-archs "i386" %s -S 2> %t
+// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: "bindings.s"' %t
// Darwin bindings
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings %s 2> %t &&
-// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: ".*\.s"' %t &&
-// RUN: grep '"darwin::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t &&
-// RUN: grep '"darwin::Link", inputs: \[".*\.o"\], output: "a.out"' %t &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings %s 2> %t
+// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: ".*\.s"' %t
+// RUN: grep '"darwin::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t
+// RUN: grep '"darwin::Link", inputs: \[".*\.o"\], output: "a.out"' %t
-// RUN: true
diff --git a/test/Driver/clang-translation.c b/test/Driver/clang-translation.c
index e0b9e3ada6ec..c57a2b76246f 100644
--- a/test/Driver/clang-translation.c
+++ b/test/Driver/clang-translation.c
@@ -1,16 +1,15 @@
-// RUN: clang -ccc-host-triple i386-unknown-unknown -### -S -O0 -Os %s -o %t.s -fverbose-asm 2> %t.log &&
-// RUN: grep '"-triple" "i386-unknown-unknown"' %t.log &&
-// RUN: grep '"-S"' %t.log &&
-// RUN: grep '"-disable-free"' %t.log &&
-// RUN: grep '"--relocation-model" "static"' %t.log &&
-// RUN: grep '"--disable-fp-elim"' %t.log &&
-// RUN: grep '"--unwind-tables=0"' %t.log &&
-// RUN: grep '"--fmath-errno=1"' %t.log &&
-// RUN: grep '"-Os"' %t.log &&
-// RUN: grep '"-o" .*clang-translation.*' %t.log &&
-// RUN: grep '"--asm-verbose"' %t.log &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S %s -o %t.s 2> %t.log &&
-// RUN: grep '"--mcpu=yonah"' %t.log &&
-// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -o %t.s 2> %t.log &&
-// RUN: grep '"--mcpu=core2"' %t.log &&
-// RUN: true
+// RUN: clang -ccc-host-triple i386-unknown-unknown -### -S -O0 -Os %s -o %t.s -fverbose-asm 2> %t.log
+// RUN: grep '"-triple" "i386-unknown-unknown"' %t.log
+// RUN: grep '"-S"' %t.log
+// RUN: grep '"-disable-free"' %t.log
+// RUN: grep '"--relocation-model" "static"' %t.log
+// RUN: grep '"--disable-fp-elim"' %t.log
+// RUN: grep '"--unwind-tables=0"' %t.log
+// RUN: grep '"--fmath-errno=1"' %t.log
+// RUN: grep '"-Os"' %t.log
+// RUN: grep '"-o" .*clang-translation.*' %t.log
+// RUN: grep '"--asm-verbose"' %t.log
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S %s -o %t.s 2> %t.log
+// RUN: grep '"--mcpu" "yonah"' %t.log
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -o %t.s 2> %t.log
+// RUN: grep '"--mcpu" "core2"' %t.log
diff --git a/test/Driver/clang_cpp.c b/test/Driver/clang_cpp.c
index fdbb321e1e91..8638465e3a2f 100644
--- a/test/Driver/clang_cpp.c
+++ b/test/Driver/clang_cpp.c
@@ -1,4 +1,4 @@
// Verify that -include isn't included twice with -save-temps.
-// RUN: clang -S -o - %s -include %t.h -save-temps -### 2> %t.log &&
+// RUN: clang -S -o - %s -include %t.h -save-temps -### 2> %t.log
// RUN: grep '"-include' %t.log | count 1
diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c
index 8266f7762398..b18f14758db1 100644
--- a/test/Driver/clang_f_opts.c
+++ b/test/Driver/clang_f_opts.c
@@ -1,11 +1,10 @@
-// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings %s 2> %t &&
-// RUN: grep -F '"-fblocks"' %t &&
-// RUN: grep -F '"--fmath-errno=1"' %t &&
-// RUN: grep -F '"-fpascal-strings"' %t &&
-// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fno-show-source-location %s 2> %t &&
-// RUN: grep -F '"-fblocks=0"' %t &&
-// RUN: grep -F '"-fbuiltin=0"' %t &&
-// RUN: grep -F '"-fno-common"' %t &&
-// RUN: grep -F '"--fmath-errno=0"' %t &&
-// RUN: grep -F '"-fno-show-source-location"' %t &&
-// RUN: true
+// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings %s 2> %t
+// RUN: grep -F '"-fblocks"' %t
+// RUN: grep -F '"--fmath-errno=1"' %t
+// RUN: grep -F '"-fpascal-strings"' %t
+// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fno-show-source-location -fshort-wchar %s 2> %t
+// RUN: grep -F '"-fbuiltin=0"' %t
+// RUN: grep -F '"-fno-common"' %t
+// RUN: grep -F '"--fmath-errno=0"' %t
+// RUN: grep -F '"-fno-show-source-location"' %t
+// RUN: grep -F '"-fshort-wchar"' %t
diff --git a/test/Driver/cxx-pth.cpp b/test/Driver/cxx-pth.cpp
index a06a25753869..508696ade885 100644
--- a/test/Driver/cxx-pth.cpp
+++ b/test/Driver/cxx-pth.cpp
@@ -1,12 +1,12 @@
// Test forced PTH for CXX support.
-// RUN: clang -x c++-header %s -### 2> %t.log &&
-// RUN: FileCheck -check-prefix EMIT -input-file %t.log %s &&
+// RUN: clang -x c++-header %s -### 2> %t.log
+// RUN: FileCheck -check-prefix EMIT -input-file %t.log %s
// EMIT: "{{.*}}/clang-cc{{.*}}" {{.*}} "-emit-pth" "{{.*}}.cpp.gch" "-x" "c++-header" "{{.*}}.cpp"
-// RUN: touch %t.h.gch &&
-// RUN: clang -E -include %t.h %s -### 2> %t.log &&
+// RUN: touch %t.h.gch
+// RUN: clang -E -include %t.h %s -### 2> %t.log
// RUN: FileCheck -check-prefix USE -input-file %t.log %s
// USE: "{{.*}}/clang-cc{{.*}}" {{.*}}"-include-pth" "{{.*}}.h.gch" {{.*}}"-x" "c++" "{{.*}}.cpp"
diff --git a/test/Driver/darwin-as.c b/test/Driver/darwin-as.c
index 486dc2e79810..26e59a5ef670 100644
--- a/test/Driver/darwin-as.c
+++ b/test/Driver/darwin-as.c
@@ -1,9 +1,9 @@
-// RUN: clang -ccc-host-triple i386-apple-darwin10 -### -x assembler -c %s -static -dynamic 2>%t &&
-// RUN: FileCheck -check-prefix=STATIC_AND_DYNAMIC-32 --input-file %t %s &&
+// RUN: clang -ccc-host-triple i386-apple-darwin10 -### -x assembler -c %s -static -dynamic 2>%t
+// RUN: FileCheck -check-prefix=STATIC_AND_DYNAMIC-32 --input-file %t %s
// CHECK-STATIC_AND_DYNAMIC-32: as{{(.exe)?}}" "-arch" "i386" "-force_cpusubtype_ALL" "-static" "-o"
-// RUN: clang -ccc-host-triple x86_64-apple-darwin10 -### -x assembler -c %s -static 2>%t &&
+// RUN: clang -ccc-host-triple x86_64-apple-darwin10 -### -x assembler -c %s -static 2>%t
// RUN: FileCheck -check-prefix=STATIC-64 --input-file %t %s
// CHECK-STATIC-64: as{{(.exe)?}}" "-arch" "x86_64" "-force_cpusubtype_ALL" "-o"
diff --git a/test/Driver/darwin-cc.c b/test/Driver/darwin-cc.c
index 77193cda4441..1f4335855b02 100644
--- a/test/Driver/darwin-cc.c
+++ b/test/Driver/darwin-cc.c
@@ -1,6 +1,5 @@
-// RUN: clang -ccc-no-clang -ccc-host-triple i386-apple-darwin10 -m32 -### -MD -g -fast -Q -dA -mkernel -ansi -aFOO -S -o /tmp/OUTPUTNAME -g0 -gfull -O2 -Werror -pedantic -Wmost -w -std=c99 -trigraphs -v -pg -fFOO -undef -Qn --param a=b -fmudflap -coverage -save-temps -nostdinc -I ARG0 -F ARG1 -I ARG2 -P -MF ARG3 -MG -MP -remap -g3 -H -D ARG4 -U ARG5 -A ARG6 -D ARG7 -U ARG8 -A ARG9 -include ARG10 -pthread %s 2> %t.log &&
-// RUN: grep ' ".*cc1" "-E" "-nostdinc" "-v" "-I" "ARG0" "-F" "ARG1" "-I" "ARG2" "-P" "-MD" "/tmp/OUTPUTNAME.d" "-MF" "ARG3" "-MG" "-MP" "-MQ" "/tmp/OUTPUTNAME" "-remap" "-dD" "-H" "-D__STATIC__" "-D_REENTRANT" "-D" "ARG4" "-U" "ARG5" "-A" "ARG6" "-D" "ARG7" "-U" "ARG8" "-A" "ARG9" "-include" "ARG10" ".*darwin-cc.c" "-D_MUDFLAP" "-include" "mf-runtime.h" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-std=c99" "-trigraphs" "-Werror" "-pedantic" "-Wmost" "-w" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-O2" "-undef" "-fpch-preprocess" "-o" ".*darwin-cc.i"' %t.log &&
-// RUN: grep ' ".*cc1" "-fpreprocessed" ".*darwin-cc.i" "-O3" "-dumpbase" ".*darwin-cc.c" "-dA" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-aFOO" "-auxbase-strip" "/tmp/OUTPUTNAME" "-g" "-g0" "-g" "-g3" "-O2" "-Werror" "-pedantic" "-Wmost" "-w" "-ansi" "-std=c99" "-trigraphs" "-version" "-p" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-undef" "-fno-ident" "-o" "/tmp/OUTPUTNAME" "--param" "a=b" "-fno-builtin" "-fno-merge-constants" "-fprofile-arcs" "-ftest-coverage"' %t.log &&
+// RUN: clang -ccc-no-clang -ccc-host-triple i386-apple-darwin10 -m32 -### -MD -g -fast -Q -dA -mkernel -ansi -aFOO -S -o /tmp/OUTPUTNAME -g0 -gfull -O2 -Werror -pedantic -Wmost -w -std=c99 -trigraphs -v -pg -fFOO -undef -Qn --param a=b -fmudflap -coverage -save-temps -nostdinc -I ARG0 -F ARG1 -I ARG2 -P -MF ARG3 -MG -MP -remap -g3 -H -D ARG4 -U ARG5 -A ARG6 -D ARG7 -U ARG8 -A ARG9 -include ARG10 -pthread %s 2> %t.log
+// RUN: grep ' ".*cc1" "-E" "-nostdinc" "-v" "-I" "ARG0" "-F" "ARG1" "-I" "ARG2" "-P" "-MD" "/tmp/OUTPUTNAME.d" "-MF" "ARG3" "-MG" "-MP" "-MQ" "/tmp/OUTPUTNAME" "-remap" "-dD" "-H" "-D__STATIC__" "-D_REENTRANT" "-D" "ARG4" "-U" "ARG5" "-A" "ARG6" "-D" "ARG7" "-U" "ARG8" "-A" "ARG9" "-include" "ARG10" ".*darwin-cc.c" "-D_MUDFLAP" "-include" "mf-runtime.h" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-std=c99" "-trigraphs" "-Werror" "-pedantic" "-Wmost" "-w" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-O2" "-undef" "-fpch-preprocess" "-o" ".*darwin-cc.i"' %t.log
+// RUN: grep ' ".*cc1" "-fpreprocessed" ".*darwin-cc.i" "-O3" "-dumpbase" ".*darwin-cc.c" "-dA" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-aFOO" "-auxbase-strip" "/tmp/OUTPUTNAME" "-g" "-g0" "-g" "-g3" "-O2" "-Werror" "-pedantic" "-Wmost" "-w" "-ansi" "-std=c99" "-trigraphs" "-version" "-p" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-undef" "-fno-ident" "-o" "/tmp/OUTPUTNAME" "--param" "a=b" "-fno-builtin" "-fno-merge-constants" "-fprofile-arcs" "-ftest-coverage"' %t.log
-// RUN: true
diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c
index 9165a4a9011f..04f35be09f1d 100644
--- a/test/Driver/darwin-ld.c
+++ b/test/Driver/darwin-ld.c
@@ -1,27 +1,27 @@
// Check that ld gets arch_multiple.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch i386 -arch x86_64 %s -### -o foo 2> %t.log &&
-// RUN: grep '".*ld.*" .*"-arch_multiple" "-final_output" "foo"' %t.log &&
-
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -filelist FOO -static 2> %t.log &&
-// RUN: grep '"-lcrt0.o" .*"-lgcc_static"' %t.log &&
-// RUN: grep '"-lgcc"' %t.log | count 0 &&
-// RUN: clang -ccc-host-triple i386-apple-darwin7 -### -filelist FOO 2> %t.log &&
-// RUN: grep '"-lcrt1.o" .*"-lgcc" "-lSystem"' %t.log &&
-// RUN: grep '"-lgcc_s"' %t.log | count 0 &&
-// RUN: clang -ccc-host-triple i386-apple-darwin8 -### -filelist FOO 2> %t.log &&
-// RUN: grep '"-lcrt1.o" .*"-lgcc_s.10.4" "-lgcc" "-lSystem"' %t.log &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -filelist FOO 2> %t.log &&
-// RUN: grep '"-lcrt1.10.5.o" .*"-lgcc_s.10.5" "-lgcc" "-lSystem"' %t.log &&
-// RUN: clang -ccc-host-triple i386-apple-darwin10 -### -filelist FOO 2> %t.log &&
-// RUN: grep '"-lcrt1.10.6.o" .*"-lSystem" "-lgcc"' %t.log &&
-// RUN: grep '"-lgcc_s"' %t.log | count 0 &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch i386 -arch x86_64 %s -### -o foo 2> %t.log
+// RUN: grep '".*ld.*" .*"-arch_multiple" "-final_output" "foo"' %t.log
+
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -filelist FOO -static 2> %t.log
+// RUN: grep '"-lcrt0.o" .*"-lgcc_static"' %t.log
+// RUN: grep '"-lgcc"' %t.log | count 0
+// RUN: clang -ccc-host-triple i386-apple-darwin7 -### -filelist FOO 2> %t.log
+// RUN: grep '"-lcrt1.o" .*"-lgcc" "-lSystem"' %t.log
+// RUN: grep '"-lgcc_s"' %t.log | count 0
+// RUN: clang -ccc-host-triple i386-apple-darwin8 -### -filelist FOO 2> %t.log
+// RUN: grep '"-lcrt1.o" .*"-lgcc_s.10.4" "-lgcc" "-lSystem"' %t.log
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -filelist FOO 2> %t.log
+// RUN: grep '"-lcrt1.10.5.o" .*"-lgcc_s.10.5" "-lgcc" "-lSystem"' %t.log
+// RUN: clang -ccc-host-triple i386-apple-darwin10 -### -filelist FOO 2> %t.log
+// RUN: grep '"-lcrt1.10.6.o" .*"-lSystem" "-lgcc"' %t.log
+// RUN: grep '"-lgcc_s"' %t.log | count 0
// Make sure we run dsymutil on source input files.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -g %s -o BAR 2> %t.log &&
-// RUN: grep '".*dsymutil" "BAR"' %t.log &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -g -filelist FOO %s -o BAR 2> %t.log &&
-// RUN: grep '".*dsymutil" "BAR"' %t.log &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -g %s -o BAR 2> %t.log
+// RUN: grep '".*dsymutil" "BAR"' %t.log
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -g -filelist FOO %s -o BAR 2> %t.log
+// RUN: grep '".*dsymutil" "BAR"' %t.log
// Splatter test case. This is gross, but it works for now. For the
// driver, just getting coverage of the tool code and checking the
@@ -32,13 +32,12 @@
//
// Note that at conception, this exactly matches gcc.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -A ARG0 -F ARG1 -L ARG2 -Mach -T ARG4 -X -Z -all_load -allowable_client ARG8 -bind_at_load -compatibility_version ARG11 -current_version ARG12 -d -dead_strip -dylib_file ARG14 -dylinker -dylinker_install_name ARG16 -dynamic -dynamiclib -e ARG19 -exported_symbols_list ARG20 -fexceptions -flat_namespace -fnested-functions -fopenmp -force_cpusubtype_ALL -fpie -fprofile-arcs -headerpad_max_install_names -image_base ARG29 -init ARG30 -install_name ARG31 -m ARG33 -miphoneos-version-min=2.0 -mmacosx-version-min=10.3.2 -multi_module -multiply_defined ARG37 -multiply_defined_unused ARG38 -no_dead_strip_inits_and_terms -nodefaultlibs -nofixprebinding -nomultidefs -noprebind -noseglinkedit -nostartfiles -nostdlib -pagezero_size ARG54 -pg -prebind -prebind_all_twolevel_modules -preload -r -read_only_relocs ARG55 -s -sectalign ARG57_0 ARG57_1 ARG57_2 -sectcreate ARG58_0 ARG58_1 ARG58_2 -sectobjectsymbols ARG59_0 ARG59_1 -sectorder ARG60_0 ARG60_1 ARG60_2 -seg1addr ARG61 -seg_addr_table ARG62 -seg_addr_table_filename ARG63 -segaddr ARG64_0 ARG64_1 -segcreate ARG65_0 ARG65_1 ARG65_2 -seglinkedit -segprot ARG67_0 ARG67_1 ARG67_2 -segs_read_FOO -segs_read_only_addr ARG69 -segs_read_write_addr ARG70 -shared-libgcc -single_module -static -static-libgcc -sub_library ARG77 -sub_umbrella ARG78 -t -twolevel_namespace -twolevel_namespace_hints -u ARG82 -umbrella ARG83 -undefined ARG84 -unexported_symbols_list ARG85 -w -weak_reference_mismatches ARG87 -whatsloaded -whyload -y -filelist FOO 2> %t.log &&
-// RUN: grep '".*ld.*" "-static" "-dylib" "-dylib_compatibility_version" "ARG11" "-dylib_current_version" "ARG12" "-arch" "i386" "-dylib_install_name" "ARG31" "-all_load" "-allowable_client" "ARG8" "-bind_at_load" "-dead_strip" "-no_dead_strip_inits_and_terms" "-dylib_file" "ARG14" "-dynamic" "-exported_symbols_list" "ARG20" "-flat_namespace" "-headerpad_max_install_names" "-image_base" "ARG29" "-init" "ARG30" "-macosx_version_min" "10.3.2" "-iphoneos_version_min" "2.0" "-nomultidefs" "-multi_module" "-single_module" "-multiply_defined" "ARG37" "-multiply_defined_unused" "ARG38" "-pie" "-prebind" "-noprebind" "-nofixprebinding" "-prebind_all_twolevel_modules" "-read_only_relocs" "ARG55" "-sectcreate" "ARG58_0" "ARG58_1" "ARG58_2" "-sectorder" "ARG60_0" "ARG60_1" "ARG60_2" "-seg1addr" "ARG61" "-segprot" "ARG67_0" "ARG67_1" "ARG67_2" "-segaddr" "ARG64_0" "ARG64_1" "-segs_read_only_addr" "ARG69" "-segs_read_write_addr" "ARG70" "-seg_addr_table" "ARG62" "-seg_addr_table_filename" "ARG63" "-sub_library" "ARG77" "-sub_umbrella" "ARG78" "-twolevel_namespace" "-twolevel_namespace_hints" "-umbrella" "ARG83" "-undefined" "ARG84" "-unexported_symbols_list" "ARG85" "-weak_reference_mismatches" "ARG87" "-X" "-y" "-w" "-pagezero_size" "ARG54" "-segs_read_FOO" "-seglinkedit" "-noseglinkedit" "-sectalign" "ARG57_0" "ARG57_1" "ARG57_2" "-sectobjectsymbols" "ARG59_0" "ARG59_1" "-segcreate" "ARG65_0" "ARG65_1" "ARG65_2" "-whyload" "-whatsloaded" "-dylinker_install_name" "ARG16" "-dylinker" "-Mach" "-d" "-s" "-t" "-Z" "-u" "ARG82" "-undefined" "ARG84" "-A" "ARG0" "-e" "ARG19" "-m" "ARG33" "-r" "-o" "a.out" "-L" "ARG2" "-lgomp" "-L/usr/lib/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1/../../../i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1/../../.." "-filelist" "FOO" "-lgcov" "-allow_stack_execute" "-T" "ARG4" "-F" "ARG1"' %t.log &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -A ARG0 -F ARG1 -L ARG2 -Mach -T ARG4 -X -Z -all_load -allowable_client ARG8 -bind_at_load -compatibility_version ARG11 -current_version ARG12 -d -dead_strip -dylib_file ARG14 -dylinker -dylinker_install_name ARG16 -dynamic -dynamiclib -e ARG19 -exported_symbols_list ARG20 -fexceptions -flat_namespace -fnested-functions -fopenmp -force_cpusubtype_ALL -fpie -fprofile-arcs -headerpad_max_install_names -image_base ARG29 -init ARG30 -install_name ARG31 -m ARG33 -miphoneos-version-min=2.0 -mmacosx-version-min=10.3.2 -multi_module -multiply_defined ARG37 -multiply_defined_unused ARG38 -no_dead_strip_inits_and_terms -nodefaultlibs -nofixprebinding -nomultidefs -noprebind -noseglinkedit -nostartfiles -nostdlib -pagezero_size ARG54 -pg -prebind -prebind_all_twolevel_modules -preload -r -read_only_relocs ARG55 -s -sectalign ARG57_0 ARG57_1 ARG57_2 -sectcreate ARG58_0 ARG58_1 ARG58_2 -sectobjectsymbols ARG59_0 ARG59_1 -sectorder ARG60_0 ARG60_1 ARG60_2 -seg1addr ARG61 -seg_addr_table ARG62 -seg_addr_table_filename ARG63 -segaddr ARG64_0 ARG64_1 -segcreate ARG65_0 ARG65_1 ARG65_2 -seglinkedit -segprot ARG67_0 ARG67_1 ARG67_2 -segs_read_FOO -segs_read_only_addr ARG69 -segs_read_write_addr ARG70 -shared-libgcc -single_module -static -static-libgcc -sub_library ARG77 -sub_umbrella ARG78 -t -twolevel_namespace -twolevel_namespace_hints -u ARG82 -umbrella ARG83 -undefined ARG84 -unexported_symbols_list ARG85 -w -weak_reference_mismatches ARG87 -whatsloaded -whyload -y -filelist FOO 2> %t.log
+// RUN: grep '".*ld.*" "-static" "-dylib" "-dylib_compatibility_version" "ARG11" "-dylib_current_version" "ARG12" "-arch" "i386" "-dylib_install_name" "ARG31" "-all_load" "-allowable_client" "ARG8" "-bind_at_load" "-dead_strip" "-no_dead_strip_inits_and_terms" "-dylib_file" "ARG14" "-dynamic" "-exported_symbols_list" "ARG20" "-flat_namespace" "-headerpad_max_install_names" "-image_base" "ARG29" "-init" "ARG30" "-macosx_version_min" "10.3.2" "-iphoneos_version_min" "2.0" "-nomultidefs" "-multi_module" "-single_module" "-multiply_defined" "ARG37" "-multiply_defined_unused" "ARG38" "-pie" "-prebind" "-noprebind" "-nofixprebinding" "-prebind_all_twolevel_modules" "-read_only_relocs" "ARG55" "-sectcreate" "ARG58_0" "ARG58_1" "ARG58_2" "-sectorder" "ARG60_0" "ARG60_1" "ARG60_2" "-seg1addr" "ARG61" "-segprot" "ARG67_0" "ARG67_1" "ARG67_2" "-segaddr" "ARG64_0" "ARG64_1" "-segs_read_only_addr" "ARG69" "-segs_read_write_addr" "ARG70" "-seg_addr_table" "ARG62" "-seg_addr_table_filename" "ARG63" "-sub_library" "ARG77" "-sub_umbrella" "ARG78" "-twolevel_namespace" "-twolevel_namespace_hints" "-umbrella" "ARG83" "-undefined" "ARG84" "-unexported_symbols_list" "ARG85" "-weak_reference_mismatches" "ARG87" "-X" "-y" "-w" "-pagezero_size" "ARG54" "-segs_read_FOO" "-seglinkedit" "-noseglinkedit" "-sectalign" "ARG57_0" "ARG57_1" "ARG57_2" "-sectobjectsymbols" "ARG59_0" "ARG59_1" "-segcreate" "ARG65_0" "ARG65_1" "ARG65_2" "-whyload" "-whatsloaded" "-dylinker_install_name" "ARG16" "-dylinker" "-Mach" "-d" "-s" "-t" "-Z" "-u" "ARG82" "-undefined" "ARG84" "-A" "ARG0" "-e" "ARG19" "-m" "ARG33" "-r" "-o" "a.out" "-L" "ARG2" "-lgomp" "-L/usr/lib/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1/../../../i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1/../../.." "-filelist" "FOO" "-lgcov" "-allow_stack_execute" "-T" "ARG4" "-F" "ARG1"' %t.log
// Don't run dsymutil on a fat build of an executable.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -arch i386 -arch x86_64 -g %s 2> %t.log &&
-// RUN: grep dsymutil %t.log | count 0 &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -arch i386 -arch x86_64 -g %s 2> %t.log
+// RUN: grep dsymutil %t.log | count 0
-// RUN: true
diff --git a/test/Driver/default-toolchain.c b/test/Driver/default-toolchain.c
index 0e8a02679e8d..9cebdfe581fe 100644
--- a/test/Driver/default-toolchain.c
+++ b/test/Driver/default-toolchain.c
@@ -1,8 +1,8 @@
-// RUN: clang -ccc-host-triple i386-unknown-unknown -m64 -v 2> %t &&
-// RUN: grep 'Target: x86_64-unknown-unknown' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -m64 -v 2> %t
+// RUN: grep 'Target: x86_64-unknown-unknown' %t
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch ppc -m64 -v 2> %t &&
-// RUN: grep 'Target: powerpc64-apple-darwin9' %t &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch ppc -m64 -v 2> %t
+// RUN: grep 'Target: powerpc64-apple-darwin9' %t
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch ppc64 -m32 -v 2> %t &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch ppc64 -m32 -v 2> %t
// RUN: grep 'Target: powerpc-apple-darwin9' %t
diff --git a/test/Driver/dragonfly.c b/test/Driver/dragonfly.c
index f0b09f7e239f..40f12e4d7f86 100644
--- a/test/Driver/dragonfly.c
+++ b/test/Driver/dragonfly.c
@@ -1,4 +1,4 @@
-// RUN: clang -ccc-host-triple amd64-pc-dragonfly %s -### 2> %t.log &&
+// RUN: clang -ccc-host-triple amd64-pc-dragonfly %s -### 2> %t.log
// RUN: FileCheck -input-file %t.log %s
// CHECK: clang-cc{{.*}}" "-triple" "amd64-pc-dragonfly"
diff --git a/test/Driver/emit-llvm.c b/test/Driver/emit-llvm.c
index a4aabe7256dc..27007c68c2fe 100644
--- a/test/Driver/emit-llvm.c
+++ b/test/Driver/emit-llvm.c
@@ -1,3 +1,3 @@
-// RUN: not clang -ccc-host-triple i386-pc-linux-gnu -emit-llvm -o %t %s 2> %t.log &&
+// RUN: not clang -ccc-host-triple i386-pc-linux-gnu -emit-llvm -o %t %s 2> %t.log
// RUN: grep 'unable to pass LLVM bit-code files to linker' %t.log
diff --git a/test/Driver/flags.c b/test/Driver/flags.c
index 7c448fa6df5b..a3241007d8fb 100644
--- a/test/Driver/flags.c
+++ b/test/Driver/flags.c
@@ -1,9 +1,9 @@
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -msoft-float %s 2> %t.log &&
-// RUN: grep '"--no-implicit-float"' %t.log &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -msoft-float %s 2> %t.log
+// RUN: grep '"--no-implicit-float"' %t.log
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -msoft-float -mno-soft-float %s 2> %t.log &&
-// RUN: grep '"--no-implicit-float"' %t.log | count 0 &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -msoft-float -mno-soft-float %s 2> %t.log
+// RUN: grep '"--no-implicit-float"' %t.log | count 0
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -mno-soft-float %s -msoft-float 2> %t.log &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -mno-soft-float %s -msoft-float 2> %t.log
// RUN: grep '"--no-implicit-float"' %t.log
diff --git a/test/Driver/freebsd.c b/test/Driver/freebsd.c
index d50c85b749de..8c03bbcfe3d6 100644
--- a/test/Driver/freebsd.c
+++ b/test/Driver/freebsd.c
@@ -1,5 +1,5 @@
-// RUN: clang -ccc-clang-archs "" -ccc-host-triple powerpc64-pc-freebsd8 %s -### 2> %t.log &&
-// RUN: cat %t.log &&
+// RUN: clang -ccc-clang-archs "" -ccc-host-triple powerpc64-pc-freebsd8 %s -### 2> %t.log
+// RUN: cat %t.log
// RUN: FileCheck -input-file %t.log %s
// CHECK: clang-cc{{.*}}" "-triple" "powerpc64-pc-freebsd8"
diff --git a/test/Driver/hello.c b/test/Driver/hello.c
index ead0d07b57ce..0df1341e4ea8 100644
--- a/test/Driver/hello.c
+++ b/test/Driver/hello.c
@@ -1,9 +1,9 @@
-// RUN: clang -ccc-echo -o %t %s 2> %t.log &&
+// RUN: clang -ccc-echo -o %t %s 2> %t.log
// Make sure we used clang.
-// RUN: grep 'clang-cc" .*hello.c' %t.log &&
+// RUN: grep 'clang-cc" .*hello.c' %t.log
-// RUN: %t > %t.out &&
+// RUN: %t > %t.out
// RUN: grep "I'm a little driver, short and stout." %t.out
// FIXME: We don't have a usable assembler on Windows, so we can't build real
diff --git a/test/Driver/immediate-options.c b/test/Driver/immediate-options.c
index 34af89f44d0e..923c30ea95ce 100644
--- a/test/Driver/immediate-options.c
+++ b/test/Driver/immediate-options.c
@@ -1,5 +1,4 @@
-// RUN: clang --help &&
-// RUN: clang --help-hidden &&
-// RUN: clang -dumpversion &&
-// RUN: clang -print-search-dirs &&
-// RUN: true
+// RUN: clang --help
+// RUN: clang --help-hidden
+// RUN: clang -dumpversion
+// RUN: clang -print-search-dirs
diff --git a/test/Driver/lto.c b/test/Driver/lto.c
index 01ef2ebc2e03..041b42461808 100644
--- a/test/Driver/lto.c
+++ b/test/Driver/lto.c
@@ -1,25 +1,24 @@
// -emit-llvm, -flto, and -O4 all cause a switch to llvm-bc object
// files.
-// RUN: clang -ccc-print-phases -c %s -flto 2> %t.log &&
-// RUN: grep '2: compiler, {1}, llvm-bc' %t.log &&
-// RUN: clang -ccc-print-phases -c %s -O4 2> %t.log &&
-// RUN: grep '2: compiler, {1}, llvm-bc' %t.log &&
+// RUN: clang -ccc-print-phases -c %s -flto 2> %t.log
+// RUN: grep '2: compiler, {1}, llvm-bc' %t.log
+// RUN: clang -ccc-print-phases -c %s -O4 2> %t.log
+// RUN: grep '2: compiler, {1}, llvm-bc' %t.log
// and -emit-llvm doesn't alter pipeline (unfortunately?).
-// RUN: clang -ccc-print-phases %s -emit-llvm 2> %t.log &&
-// RUN: grep '0: input, ".*lto.c", c' %t.log &&
-// RUN: grep '1: preprocessor, {0}, cpp-output' %t.log &&
-// RUN: grep '2: compiler, {1}, llvm-bc' %t.log &&
-// RUN: grep '3: linker, {2}, image' %t.log &&
+// RUN: clang -ccc-print-phases %s -emit-llvm 2> %t.log
+// RUN: grep '0: input, ".*lto.c", c' %t.log
+// RUN: grep '1: preprocessor, {0}, cpp-output' %t.log
+// RUN: grep '2: compiler, {1}, llvm-bc' %t.log
+// RUN: grep '3: linker, {2}, image' %t.log
// llvm-bc and llvm-ll outputs need to match regular suffixes
// (unfortunately).
-// RUN: clang %s -emit-llvm -save-temps -### 2> %t.log &&
-// RUN: grep '"-o" ".*lto\.i" "-x" "c" ".*lto\.c"' %t.log &&
-// RUN: grep '"-o" ".*lto\.o" .*".*lto\.i"' %t.log &&
-// RUN: grep '".*a.out" .*".*lto\.o"' %t.log &&
+// RUN: clang %s -emit-llvm -save-temps -### 2> %t.log
+// RUN: grep '"-o" ".*lto\.i" "-x" "c" ".*lto\.c"' %t.log
+// RUN: grep '"-o" ".*lto\.o" .*".*lto\.i"' %t.log
+// RUN: grep '".*a.out" .*".*lto\.o"' %t.log
-// RUN: clang %s -emit-llvm -S -### 2> %t.log &&
-// RUN: grep '"-o" ".*lto\.s" "-x" "c" ".*lto\.c"' %t.log &&
+// RUN: clang %s -emit-llvm -S -### 2> %t.log
+// RUN: grep '"-o" ".*lto\.s" "-x" "c" ".*lto\.c"' %t.log
-// RUN: true
diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c
index c73ef20d8045..8b0706b28fdc 100644
--- a/test/Driver/openbsd.c
+++ b/test/Driver/openbsd.c
@@ -1,4 +1,4 @@
-// RUN: clang -ccc-clang-archs "" -ccc-host-triple i686-pc-openbsd %s -### 2> %t.log &&
+// RUN: clang -ccc-clang-archs "" -ccc-host-triple i686-pc-openbsd %s -### 2> %t.log
// RUN: FileCheck -input-file %t.log %s
// CHECK: clang-cc{{.*}}" "-triple" "i686-pc-openbsd"
diff --git a/test/Driver/parsing.c b/test/Driver/parsing.c
index 7b6444050d7d..8e37128e3ed9 100644
--- a/test/Driver/parsing.c
+++ b/test/Driver/parsing.c
@@ -1,24 +1,23 @@
-// RUN: clang -ccc-print-options input -Yunknown -m32 -arch ppc -djoined -A separate -Ajoined -Wp,one,two -Xarch_joined AndSeparate -sectalign 1 2 3 2> %t &&
-// RUN: grep 'Option 0 - Name: "<input>", Values: {"input"}' %t &&
-// RUN: grep 'Option 1 - Name: "<unknown>", Values: {"-Yunknown"}' %t &&
-// RUN: grep 'Option 2 - Name: "-m32", Values: {}' %t &&
-// RUN: grep 'Option 3 - Name: "-arch", Values: {"ppc"}' %t &&
-// RUN: grep 'Option 4 - Name: "-d", Values: {"joined"}' %t &&
-// RUN: grep 'Option 5 - Name: "-A", Values: {"separate"}' %t &&
-// RUN: grep 'Option 6 - Name: "-A", Values: {"joined"}' %t &&
-// RUN: grep 'Option 7 - Name: "-Wp,", Values: {"one", "two"}' %t &&
-// RUN: grep 'Option 8 - Name: "-Xarch_", Values: {"joined", "AndSeparate"}' %t &&
-// RUN: grep 'Option 9 - Name: "-sectalign", Values: {"1", "2", "3"}' %t &&
+// RUN: clang -ccc-print-options input -Yunknown -m32 -arch ppc -djoined -A separate -Ajoined -Wp,one,two -Xarch_joined AndSeparate -sectalign 1 2 3 2> %t
+// RUN: grep 'Option 0 - Name: "<input>", Values: {"input"}' %t
+// RUN: grep 'Option 1 - Name: "<unknown>", Values: {"-Yunknown"}' %t
+// RUN: grep 'Option 2 - Name: "-m32", Values: {}' %t
+// RUN: grep 'Option 3 - Name: "-arch", Values: {"ppc"}' %t
+// RUN: grep 'Option 4 - Name: "-d", Values: {"joined"}' %t
+// RUN: grep 'Option 5 - Name: "-A", Values: {"separate"}' %t
+// RUN: grep 'Option 6 - Name: "-A", Values: {"joined"}' %t
+// RUN: grep 'Option 7 - Name: "-Wp,", Values: {"one", "two"}' %t
+// RUN: grep 'Option 8 - Name: "-Xarch_", Values: {"joined", "AndSeparate"}' %t
+// RUN: grep 'Option 9 - Name: "-sectalign", Values: {"1", "2", "3"}' %t
-// RUN: not clang -V 2> %t &&
-// RUN: grep "error: argument to '-V' is missing (expected 1 value)" %t &&
-// RUN: not clang -sectalign 1 2 2> %t &&
-// RUN: grep "error: argument to '-sectalign' is missing (expected 3 values)" %t &&
+// RUN: not clang -V 2> %t
+// RUN: grep "error: argument to '-V' is missing (expected 1 value)" %t
+// RUN: not clang -sectalign 1 2 2> %t
+// RUN: grep "error: argument to '-sectalign' is missing (expected 3 values)" %t
// Verify that search continues after find the first option.
-// RUN: clang -ccc-print-options -Wally 2> %t &&
-// RUN: grep 'Option 0 - Name: "-W", Values: {"ally"}' %t &&
+// RUN: clang -ccc-print-options -Wally 2> %t
+// RUN: grep 'Option 0 - Name: "-W", Values: {"ally"}' %t
-// RUN: true
diff --git a/test/Driver/phases.c b/test/Driver/phases.c
index 61f68c452835..d03bff9a77b1 100644
--- a/test/Driver/phases.c
+++ b/test/Driver/phases.c
@@ -1,5 +1,5 @@
// Basic compilation for various types of files.
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c %s -x objective-c %s -x c++ %s -x objective-c++ -x assembler %s -x assembler-with-cpp %s -x none %s 2>&1 | FileCheck -check-prefix=BASIC %s &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c %s -x objective-c %s -x c++ %s -x objective-c++ -x assembler %s -x assembler-with-cpp %s -x none %s 2>&1 | FileCheck -check-prefix=BASIC %s
// BASIC: 0: input, "{{.*}}phases.c", c
// BASIC: 1: preprocessor, {0}, cpp-output
// BASIC: 2: compiler, {1}, assembler
@@ -24,7 +24,7 @@
// BASIC: 21: linker, {3, 7, 11, 13, 16, 20}, image
// Universal linked image.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=ULI %s &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=ULI %s
// ULI: 0: input, "{{.*}}phases.c", c
// ULI: 1: preprocessor, {0}, cpp-output
// ULI: 2: compiler, {1}, assembler
@@ -35,7 +35,7 @@
// ULI: 7: lipo, {5, 6}, image
// Universal object file.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=UOF %s &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=UOF %s
// UOF: 0: input, "{{.*}}phases.c", c
// UOF: 1: preprocessor, {0}, cpp-output
// UOF: 2: compiler, {1}, assembler
@@ -45,35 +45,34 @@
// UOF: 6: lipo, {4, 5}, object
// Arch defaulting
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s 2>&1 | FileCheck -check-prefix=ARCH1 %s &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s 2>&1 | FileCheck -check-prefix=ARCH1 %s
// ARCH1: 2: bind-arch, "i386", {1}, object
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s -m32 -m64 2>&1 | FileCheck -check-prefix=ARCH2 %s &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s -m32 -m64 2>&1 | FileCheck -check-prefix=ARCH2 %s
// ARCH2: 2: bind-arch, "x86_64", {1}, object
-// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s 2>&1 | FileCheck -check-prefix=ARCH3 %s &&
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s 2>&1 | FileCheck -check-prefix=ARCH3 %s
// ARCH3: 2: bind-arch, "x86_64", {1}, object
-// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s -m64 -m32 2>&1 | FileCheck -check-prefix=ARCH4 %s &&
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s -m64 -m32 2>&1 | FileCheck -check-prefix=ARCH4 %s
// ARCH4: 2: bind-arch, "i386", {1}, object
// Analyzer
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases --analyze %s 2>&1 | FileCheck -check-prefix=ANALYZE %s &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases --analyze %s 2>&1 | FileCheck -check-prefix=ANALYZE %s
// ANALYZE: 0: input, "{{.*}}phases.c", c
// ANALYZE: 1: preprocessor, {0}, cpp-output
// ANALYZE: 2: analyzer, {1}, plist
// Precompiler
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c-header %s 2>&1 | FileCheck -check-prefix=PCH %s &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c-header %s 2>&1 | FileCheck -check-prefix=PCH %s
// PCH: 0: input, "{{.*}}phases.c", c-header
// PCH: 1: preprocessor, {0}, c-header-cpp-output
// PCH: 2: precompiler, {1}, precompiled-header
// Darwin overrides the handling for .s
-// RUN: touch %t.s &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -c %t.s 2>&1 | FileCheck -check-prefix=DARWIN1 %s &&
+// RUN: touch %t.s
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -c %t.s 2>&1 | FileCheck -check-prefix=DARWIN1 %s
// DARWIN1: 0: input, "{{.*}}.s", assembler
// DARWIN1: 1: assembler, {0}, object
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c %t.s 2>&1 | FileCheck -check-prefix=DARWIN2 %s &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c %t.s 2>&1 | FileCheck -check-prefix=DARWIN2 %s
// DARWIN2: 0: input, "{{.*}}.s", assembler-with-cpp
// DARWIN2: 1: preprocessor, {0}, assembler
// DARWIN2: 2: assembler, {1}, object
-// RUN: true
diff --git a/test/Driver/preprocessor.c b/test/Driver/preprocessor.c
index ec1f42f5bafd..51b6fc57867e 100644
--- a/test/Driver/preprocessor.c
+++ b/test/Driver/preprocessor.c
@@ -1,4 +1,4 @@
-// RUN: clang -E -x c-header %s > %t &&
+// RUN: clang -E -x c-header %s > %t
// RUN: grep 'B B' %t
#define A B
diff --git a/test/Driver/pth.c b/test/Driver/pth.c
index 5c83aea54ceb..8e8b2dda32ba 100644
--- a/test/Driver/pth.c
+++ b/test/Driver/pth.c
@@ -1,12 +1,12 @@
// Test transparent PTH support.
-// RUN: clang -ccc-pch-is-pth -x c-header %s -o %t.h.pth -### 2> %t.log &&
-// RUN: FileCheck -check-prefix CHECK1 -input-file %t.log %s &&
+// RUN: clang -ccc-pch-is-pth -x c-header %s -o %t.h.pth -### 2> %t.log
+// RUN: FileCheck -check-prefix CHECK1 -input-file %t.log %s
// CHECK1: "{{.*}}/clang-cc{{.*}}" {{.*}} "-o" "{{.*}}.h.pth" "-x" "c-header" "{{.*}}pth.c"
-// RUN: touch %t.h.pth &&
-// RUN: clang -ccc-pch-is-pth -E -include %t.h %s -### 2> %t.log &&
+// RUN: touch %t.h.pth
+// RUN: clang -ccc-pch-is-pth -E -include %t.h %s -### 2> %t.log
// RUN: FileCheck -check-prefix CHECK2 -input-file %t.log %s
// CHECK2: "{{.*}}/clang-cc{{.*}}" {{.*}}"-include-pth" "{{.*}}.h.pth" {{.*}}"-x" "c" "{{.*}}pth.c"
diff --git a/test/Driver/redzone.c b/test/Driver/redzone.c
index 64729ac27717..86f412fb4690 100644
--- a/test/Driver/redzone.c
+++ b/test/Driver/redzone.c
@@ -1,6 +1,6 @@
-// RUN: clang -ccc-host-triple i386-unknown-unknown -mno-red-zone %s -S -emit-llvm -o %t.log &&
-// RUN: grep 'noredzone' %t.log &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -mred-zone %s -S -emit-llvm -o %t.log &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -mno-red-zone %s -S -emit-llvm -o %t.log
+// RUN: grep 'noredzone' %t.log
+// RUN: clang -ccc-host-triple i386-unknown-unknown -mred-zone %s -S -emit-llvm -o %t.log
// RUN: grep -v 'noredzone' %t.log
int foo() { return 42; }
diff --git a/test/Driver/std.c b/test/Driver/std.c
index 04113d5af134..01a5f7ccec25 100644
--- a/test/Driver/std.c
+++ b/test/Driver/std.c
@@ -1,6 +1,6 @@
-// RUN: clang -std=c99 -trigraphs -std=gnu99 %s -E -o - | FileCheck -check-prefix=OVERRIDE %s &&
+// RUN: clang -std=c99 -trigraphs -std=gnu99 %s -E -o - | FileCheck -check-prefix=OVERRIDE %s
// OVERRIDE: ??(??)
-// RUN: clang -ansi %s -E -o - | FileCheck -check-prefix=ANSI %s &&
+// RUN: clang -ansi %s -E -o - | FileCheck -check-prefix=ANSI %s
// ANSI: []
// RUN: clang -std=gnu99 -trigraphs %s -E -o - | FileCheck -check-prefix=EXPLICIT %s
// EXPLICIT: []
diff --git a/test/Driver/unknown-gcc-arch.c b/test/Driver/unknown-gcc-arch.c
index de9e8e84c4ae..e8b653fbceab 100644
--- a/test/Driver/unknown-gcc-arch.c
+++ b/test/Driver/unknown-gcc-arch.c
@@ -1,8 +1,8 @@
-// RUN: clang -ccc-host-triple x86_64-unknown-unknown -c -x assembler %s -### 2> %t.log &&
-// RUN: grep '.*gcc.*"-m64"' %t.log &&
-// RUN: clang -ccc-host-triple x86_64-unknown-unknown -c -x assembler %s -### -m32 2> %t.log &&
-// RUN: grep '.*gcc.*"-m32"' %t.log &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -c -x assembler %s -### 2> %t.log &&
-// RUN: grep '.*gcc.*"-m32"' %t.log &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -c -x assembler %s -### -m64 2> %t.log &&
+// RUN: clang -ccc-host-triple x86_64-unknown-unknown -c -x assembler %s -### 2> %t.log
+// RUN: grep '.*gcc.*"-m64"' %t.log
+// RUN: clang -ccc-host-triple x86_64-unknown-unknown -c -x assembler %s -### -m32 2> %t.log
+// RUN: grep '.*gcc.*"-m32"' %t.log
+// RUN: clang -ccc-host-triple i386-unknown-unknown -c -x assembler %s -### 2> %t.log
+// RUN: grep '.*gcc.*"-m32"' %t.log
+// RUN: clang -ccc-host-triple i386-unknown-unknown -c -x assembler %s -### -m64 2> %t.log
// RUN: grep '.*gcc.*"-m64"' %t.log
diff --git a/test/Driver/x86_features.c b/test/Driver/x86_features.c
index efb3681f9de0..d0473b38bb1e 100644
--- a/test/Driver/x86_features.c
+++ b/test/Driver/x86_features.c
@@ -1,3 +1,3 @@
-// RUN: clang -ccc-host-triple i386-unknown-unknown -### -S %s -msse -msse4 -mno-sse -mno-mmx -msse 2> %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -### -S %s -msse -msse4 -mno-sse -mno-mmx -msse 2> %t
// RUN: grep '"-target-feature" "+sse" "-target-feature" "+sse4" "-target-feature" "-sse" "-target-feature" "-mmx" "-target-feature" "+sse"' %t
diff --git a/test/FixIt/fixit-at.c b/test/FixIt/fixit-at.c
index 42488f56bc7b..5eaa5c346926 100644
--- a/test/FixIt/fixit-at.c
+++ b/test/FixIt/fixit-at.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -fixit-at=fixit-at.c:3:1 %s -o - | clang-cc -verify -x c -
+// RUN: clang-cc -fixit-at=fixit-at.c:3:1 %s -o - | clang-cc -verify -x c -
_Complex cd;
diff --git a/test/FixIt/fixit-c90.c b/test/FixIt/fixit-c90.c
index 03c94953db4e..7036b08022c0 100644
--- a/test/FixIt/fixit-c90.c
+++ b/test/FixIt/fixit-c90.c
@@ -1,4 +1,4 @@
-/* RUN: clang-cc -fsyntax-only -std=c90 -pedantic -fixit %s -o - | clang-cc -pedantic -x c -std=c90 -Werror -
+/* RUN: clang-cc -std=c90 -pedantic -fixit %s -o - | clang-cc -pedantic -x c -std=c90 -Werror -
*/
/* This is a test of the various code modification hints that are
diff --git a/test/FixIt/fixit-errors-1.c b/test/FixIt/fixit-errors-1.c
index 14329ead8599..968d1d23151c 100644
--- a/test/FixIt/fixit-errors-1.c
+++ b/test/FixIt/fixit-errors-1.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c -
+// RUN: clang-cc -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c -
/* This is a test of the various code modification hints that are
provided as part of warning or extension diagnostics. All of the
diff --git a/test/FixIt/fixit-errors.c b/test/FixIt/fixit-errors.c
index 9c5258dbcb74..030f505e610e 100644
--- a/test/FixIt/fixit-errors.c
+++ b/test/FixIt/fixit-errors.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c -
+// RUN: clang-cc -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c -
/* This is a test of the various code modification hints that are
provided as part of warning or extension diagnostics. All of the
@@ -8,3 +8,13 @@
struct s; // expected-note{{previous use is here}}
union s *s1; // expected-error{{use of 's' with tag type that does not match previous declaration}}
+
+struct Point {
+ float x, y, z;
+};
+
+struct Point *get_origin();
+
+void test_point() {
+ (void)get_origin->x;
+}
diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m
index baef2337c10c..21aebfe3a968 100644
--- a/test/FixIt/fixit-objc.m
+++ b/test/FixIt/fixit-objc.m
@@ -1,8 +1,36 @@
-// RUN: clang-cc -fsyntax-only -fixit-at=fixit-at.c:3:1 %s -o %t.m &&
-// RUN: clang-cc -verify %t.m
+// RUN: clang-cc -pedantic -fixit %s -o %t
+// RUN: clang-cc -pedantic -x objective-c %t -verify
+
+/* This is a test of the various code modification hints that are
+ provided as part of warning or extension diagnostics. All of the
+ warnings will be fixed by -fixit, and the resulting file should
+ compile cleanly with -Werror -pedantic. */
@protocol X;
void foo() {
<X> *P; // should be fixed to 'id<X>'.
}
+
+@class A;
+@class NSString;
+
+@interface Test
+- (void)test:(NSString *)string;
+
+@property (copy) NSString *property;
+@end
+
+void g(NSString *a);
+void h(id a);
+
+void f(Test *t) {
+ NSString *a = "Foo";
+ id b = "Foo";
+ A* c = "Foo"; // expected-warning {{incompatible pointer types initializing 'char [4]', expected 'A *'}}
+ g("Foo");
+ h("Foo");
+ h(("Foo"));
+ [t test:"Foo"];
+ t.property = "Foo";
+}
diff --git a/test/FixIt/fixit-pmem.cpp b/test/FixIt/fixit-pmem.cpp
index bb36f7fa9343..f938009b9030 100644
--- a/test/FixIt/fixit-pmem.cpp
+++ b/test/FixIt/fixit-pmem.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -fsyntax-only -pedantic -Werror -x c++ -
+// RUN: clang-cc -pedantic -fixit %s -o - | clang-cc -fsyntax-only -pedantic -Werror -x c++ -
/* This is a test of the various code modification hints that are
provided as part of warning or extension diagnostics. All of the
diff --git a/test/FixIt/fixit.c b/test/FixIt/fixit.c
index 1378df4de152..4a32682be052 100644
--- a/test/FixIt/fixit.c
+++ b/test/FixIt/fixit.c
@@ -1,10 +1,14 @@
-// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c -
+// RUN: clang-cc -pedantic -fixit %s -o - | grep -v 'CHECK' > %t
+// RUN: clang-cc -pedantic -Werror -x c -
+// RUN: FileCheck -input-file=%t %s
/* This is a test of the various code modification hints that are
provided as part of warning or extension diagnostics. All of the
warnings will be fixed by -fixit, and the resulting file should
compile cleanly with -Werror -pedantic. */
-#include <string.h> // FIXME: FIX-IT hint should add this for us!
+
+// FIXME: FIX-IT should add #include <string.h>?
+int strcmp(const char *s1, const char *s2);
void f0(void) { };
@@ -12,9 +16,13 @@ struct s {
int x, y;;
};
+// CHECK: _Complex double cd;
_Complex cd;
+// CHECK: struct s s0 = { .y = 5 };
struct s s0 = { y: 5 };
+
+// CHECK: int array0[5] = { [3] = 3 };
int array0[5] = { [3] 3 };
void f1(x, y)
@@ -25,5 +33,7 @@ int i0 = { 17 };
int f2(const char *my_string) {
// FIXME: terminal output isn't so good when "my_string" is shorter
+// CHECK: return strcmp(my_string , "foo") == 0;
return my_string == "foo";
}
+
diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp
index ccddd959452b..dac1fa03de37 100644
--- a/test/FixIt/fixit.cpp
+++ b/test/FixIt/fixit.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -fsyntax-only -pedantic -Werror -x c++ -
+// RUN: clang-cc -pedantic -fixit %s -o - | clang-cc -fsyntax-only -pedantic -Werror -x c++ -
/* This is a test of the various code modification hints that are
provided as part of warning or extension diagnostics. All of the
@@ -27,3 +27,12 @@ public:
struct CT<0> { }; // expected-error{{'template<>'}}
template<> class CT<1> { }; // expected-error{{tag type}}
+
+// PR5444
+namespace PR5444 {
+ void foo(int x, int y = 0);
+ void foo(int x, int y = 0) { }
+
+ void foo(int = 0);
+ void foo(int = 0) { }
+}
diff --git a/test/Frontend/ast-codegen.c b/test/Frontend/ast-codegen.c
index 1fe74d4fbeb4..bd8a20adb69b 100644
--- a/test/Frontend/ast-codegen.c
+++ b/test/Frontend/ast-codegen.c
@@ -1,4 +1,4 @@
-// RUN: clang -emit-ast -o %t.ast %s &&
+// RUN: clang -emit-ast -o %t.ast %s
// RUN: clang -emit-llvm -S -o - %t.ast | FileCheck %s
// CHECK: module asm "foo"
diff --git a/test/Frontend/ast-main.c b/test/Frontend/ast-main.c
index 783140673899..ef072b92f9c1 100644
--- a/test/Frontend/ast-main.c
+++ b/test/Frontend/ast-main.c
@@ -1,6 +1,6 @@
-// RUN: clang -emit-llvm -S -o %t1.ll -x c - < %s &&
-// RUN: clang -emit-ast -o %t.ast %s &&
-// RUN: clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast &&
+// RUN: clang -emit-llvm -S -o %t1.ll -x c - < %s
+// RUN: clang -emit-ast -o %t.ast %s
+// RUN: clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
// RUN: diff %t1.ll %t2.ll
int main() {
diff --git a/test/Frontend/cpp-output.c b/test/Frontend/cpp-output.c
index ee37f4cd6853..9a6fc9b21425 100644
--- a/test/Frontend/cpp-output.c
+++ b/test/Frontend/cpp-output.c
@@ -1,10 +1,9 @@
-// RUN: clang -E -o %t -C %s &&
-// RUN: grep '^int x; // comment' %t &&
-// RUN: grep '^x x' %t &&
-// RUN: clang -E -o %t -CC %s &&
-// RUN: grep '^int x; // comment' %t &&
-// RUN: grep '^x /\* comment \*/ x /\* comment \*/' %t &&
-// RUN: true
+// RUN: clang -E -o %t -C %s
+// RUN: grep '^int x; // comment' %t
+// RUN: grep '^x x' %t
+// RUN: clang -E -o %t -CC %s
+// RUN: grep '^int x; // comment' %t
+// RUN: grep '^x /\* comment \*/ x /\* comment \*/' %t
int x; // comment
diff --git a/test/Frontend/darwin-version.c b/test/Frontend/darwin-version.c
index 3217b9ad5e3b..4896aecdfae5 100644
--- a/test/Frontend/darwin-version.c
+++ b/test/Frontend/darwin-version.c
@@ -1,23 +1,22 @@
-// RUN: clang -ccc-host-triple armv6-apple-darwin9 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '30000' | count 1 &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0 &&
-// RUN: clang -ccc-host-triple armv6-apple-darwin9 -miphoneos-version-min=2.0 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20000' | count 1 &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0 &&
-// RUN: clang -ccc-host-triple armv6-apple-darwin9 -miphoneos-version-min=2.2 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20200' | count 1 &&
-// RUN: clang -ccc-host-triple i686-apple-darwin8 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0 &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1 &&
-// RUN: clang -ccc-host-triple i686-apple-darwin9 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1 &&
-// RUN: clang -ccc-host-triple i686-apple-darwin10 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1 &&
-// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.4 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0 &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1 &&
-// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.5 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1 &&
-// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.6 -dM -E -o %t %s &&
-// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1 &&
-// RUN: true
+// RUN: clang -ccc-host-triple armv6-apple-darwin9 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '30000' | count 1
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0
+// RUN: clang -ccc-host-triple armv6-apple-darwin9 -miphoneos-version-min=2.0 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20000' | count 1
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0
+// RUN: clang -ccc-host-triple armv6-apple-darwin9 -miphoneos-version-min=2.2 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20200' | count 1
+// RUN: clang -ccc-host-triple i686-apple-darwin8 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1
+// RUN: clang -ccc-host-triple i686-apple-darwin10 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.4 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.5 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.6 -dM -E -o %t %s
+// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1
diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c
index 458d8d58b2ee..9185921407da 100644
--- a/test/Frontend/dependency-gen.c
+++ b/test/Frontend/dependency-gen.c
@@ -1,8 +1,8 @@
// rdar://6533411
-// RUN: clang -MD -MF %t.d -S -x c -o %t.o %s &&
-// RUN: grep '.*dependency-gen.*:' %t.d &&
-// RUN: grep 'dependency-gen.c' %t.d &&
+// RUN: clang -MD -MF %t.d -S -x c -o %t.o %s
+// RUN: grep '.*dependency-gen.*:' %t.d
+// RUN: grep 'dependency-gen.c' %t.d
-// RUN: clang -S -M -x c %s -o %t.d &&
-// RUN: grep '.*dependency-gen.*:' %t.d &&
+// RUN: clang -S -M -x c %s -o %t.d
+// RUN: grep '.*dependency-gen.*:' %t.d
// RUN: grep 'dependency-gen.c' %t.d
diff --git a/test/Frontend/rewrite-macros.c b/test/Frontend/rewrite-macros.c
index 32e02ecb266f..2d9fef40035b 100644
--- a/test/Frontend/rewrite-macros.c
+++ b/test/Frontend/rewrite-macros.c
@@ -1,18 +1,17 @@
-// RUN: clang-cc -verify --rewrite-macros -o %t %s &&
+// RUN: clang-cc -verify --rewrite-macros -o %t %s
#define A(a,b) a ## b
-// RUN: grep '12 */\*A\*/ /\*(1,2)\*/' %t &&
+// RUN: grep '12 */\*A\*/ /\*(1,2)\*/' %t
A(1,2)
-// RUN: grep '/\*_Pragma("mark")\*/' %t &&
+// RUN: grep '/\*_Pragma("mark")\*/' %t
_Pragma("mark")
-// RUN: grep "//#warning eek" %t &&
+// RUN: grep "//#warning eek" %t
/* expected-warning {{#warning eek}} */ #warning eek
-// RUN: grep "//#pragma mark mark" %t &&
+// RUN: grep "//#pragma mark mark" %t
#pragma mark mark
-// RUN: true
diff --git a/test/Frontend/stdin.c b/test/Frontend/stdin.c
index 5b719b2e1344..35fe45d35b40 100644
--- a/test/Frontend/stdin.c
+++ b/test/Frontend/stdin.c
@@ -1,3 +1,3 @@
-// RUN: clang-cc -E - < /dev/null > %t &&
+// RUN: clang-cc -E - < /dev/null > %t
// RUN: grep '<built-in>' %t
diff --git a/test/Index/Inputs/c-index-pch.h b/test/Index/Inputs/c-index-pch.h
new file mode 100644
index 000000000000..6dda18000c2f
--- /dev/null
+++ b/test/Index/Inputs/c-index-pch.h
@@ -0,0 +1,7 @@
+#ifndef C_INDEX_PCH_H
+#define C_INDEX_PCH_H
+
+void foo(int i, float f);
+extern int bar;
+
+#endif // C_INDEX_PCH_H
diff --git a/test/Index/Inputs/foo.h b/test/Index/Inputs/foo.h
new file mode 100644
index 000000000000..7670c00dfbfe
--- /dev/null
+++ b/test/Index/Inputs/foo.h
@@ -0,0 +1,8 @@
+extern int global_var;
+
+void foo_func(int param1);
+void bar_func(void);
+
+struct MyStruct {
+ int field_var;
+};
diff --git a/test/Index/Inputs/lit.local.cfg b/test/Index/Inputs/lit.local.cfg
new file mode 100644
index 000000000000..e6f55eef7af5
--- /dev/null
+++ b/test/Index/Inputs/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = []
diff --git a/test/Index/Inputs/objc.h b/test/Index/Inputs/objc.h
new file mode 100644
index 000000000000..c671addde59f
--- /dev/null
+++ b/test/Index/Inputs/objc.h
@@ -0,0 +1,11 @@
+@interface Base {
+ int my_var;
+}
+-(int) my_var;
+-(void) my_method: (int)param;
++(void) my_method: (int)param;
+@end
+
+@interface Sub : Base
+-(void) my_method: (int)param;
+@end
diff --git a/test/Index/Inputs/t1.c b/test/Index/Inputs/t1.c
new file mode 100644
index 000000000000..ceaad4c7f3a6
--- /dev/null
+++ b/test/Index/Inputs/t1.c
@@ -0,0 +1,28 @@
+#include "foo.h"
+
+void foo_func(int param1) {
+ int local_var = global_var;
+ for (int for_var = 100; for_var < 500; ++for_var) {
+ local_var = param1 + for_var;
+ }
+ bar_func();
+}
+
+struct S1 {
+ int x;
+};
+
+struct S2 {
+ int x;
+};
+
+void field_test(void) {
+ struct S1 s1;
+ s1.x = 0;
+ ((struct S2 *)0)->x = 0;
+
+ struct MyStruct ms;
+ ms.field_var = 10;
+}
+
+int (^CP)(int) = ^(int x) { return x * global_var; };
diff --git a/test/Index/Inputs/t1.m b/test/Index/Inputs/t1.m
new file mode 100644
index 000000000000..b7c86cd6aac7
--- /dev/null
+++ b/test/Index/Inputs/t1.m
@@ -0,0 +1,20 @@
+#include "objc.h"
+
+static void foo() {
+ Base *base;
+ int x = [base my_var];
+ [base my_method:x];
+ [Base my_method:x];
+}
+
+@implementation Base
+-(int) my_var {
+ return my_var;
+}
+
+-(void) my_method: (int)param {
+}
+
++(void) my_method: (int)param {
+}
+@end
diff --git a/test/Index/Inputs/t2.c b/test/Index/Inputs/t2.c
new file mode 100644
index 000000000000..76d5d6ceeb41
--- /dev/null
+++ b/test/Index/Inputs/t2.c
@@ -0,0 +1,11 @@
+#include "foo.h"
+
+int global_var = 10;
+
+void bar_func(void) {
+ global_var += 100;
+ foo_func(global_var);
+
+ struct MyStruct *ms;
+ ms->field_var = 10;
+}
diff --git a/test/Index/Inputs/t2.m b/test/Index/Inputs/t2.m
new file mode 100644
index 000000000000..3f103eeb1dc7
--- /dev/null
+++ b/test/Index/Inputs/t2.m
@@ -0,0 +1,13 @@
+#include "objc.h"
+
+static void foo() {
+ Sub *sub;
+ int x = [sub my_var];
+ [sub my_method:x];
+ [Sub my_method:x];
+}
+
+@implementation Sub
+-(void) my_method: (int)param {
+}
+@end
diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m
new file mode 100644
index 000000000000..7256d2bffaf5
--- /dev/null
+++ b/test/Index/TestClassDecl.m
@@ -0,0 +1,52 @@
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast
+// RUN: c-index-test -test-file-scan %t.ast %s | FileCheck -check-prefix=scan %s
+// RUN: c-index-test -test-load-tu %t.ast local | FileCheck -check-prefix=load %s
+
+// This test checks how the @class resolves as a cursor when there is a real definition
+// that follows. <rdar://problem/7383421>
+
+@class Foo;
+
+@interface Foo
+@end
+
+void function(Foo * arg)
+{
+ // nothing here.
+}
+
+// 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=11 end_col=1} ObjCInterfaceDecl=Foo:10:1
+// CHECK-scan: {start_line=11 start_col=2 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=52 end_col=1} Invalid Cursor => NoDeclFound
+
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:0:0: StructDecl=objc_selector:0:0 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=SEL:0:0 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:0:0: ObjCInterfaceDecl=Protocol:0:0 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=id:0:0 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=Class:0:0 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:80:16: StructDecl=__va_list_tag:80:16 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:80:42: FieldDecl=gp_offset:80:42 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:63: FieldDecl=fp_offset:80:63 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:81: FieldDecl=overflow_arg_area:80:81 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:107: FieldDecl=reg_save_area:80:107 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:123: TypedefDecl=__va_list_tag:80:123 [Context=TestClassDecl.m]
+// CHECK-load: <invalid loc>:80:159: TypedefDecl=__builtin_va_list:80:159 [Context=TestClassDecl.m]
+// CHECK-load: TestClassDecl.m:10:12: ObjCInterfaceDecl=Foo:10:1 [Context=TestClassDecl.m]
+// CHECK-load: TestClassDecl.m:13:6: FunctionDefn=function [Context=TestClassDecl.m]
+// CHECK-load: TestClassDecl.m:13:21: ParmDecl=arg:13:21 [Context=function]
+
diff --git a/test/Index/TestClassForwardDecl.m b/test/Index/TestClassForwardDecl.m
new file mode 100644
index 000000000000..4584445d0b9e
--- /dev/null
+++ b/test/Index/TestClassForwardDecl.m
@@ -0,0 +1,46 @@
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast
+// RUN: c-index-test -test-file-scan %t.ast %s | FileCheck -check-prefix=scan %s
+// RUN: c-index-test -test-load-tu %t.ast local | FileCheck -check-prefix=load %s
+
+// This test checks how the @class resolves as a cursor when the @interface is implicitly defined.
+// See TestClassDecl.m for the corresponding test case. (<rdar://problem/7383421>)
+
+@class Foo;
+
+void function(Foo * arg)
+{
+ // nothing here.
+}
+
+// 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-load: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:0:0: StructDecl=objc_selector:0:0 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=SEL:0:0 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:0:0: ObjCInterfaceDecl=Protocol:0:0 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=id:0:0 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:0:0: TypedefDecl=Class:0:0 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:80:16: StructDecl=__va_list_tag:80:16 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:80:42: FieldDecl=gp_offset:80:42 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:63: FieldDecl=fp_offset:80:63 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:81: FieldDecl=overflow_arg_area:80:81 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:107: FieldDecl=reg_save_area:80:107 [Context=__va_list_tag]
+// CHECK-load: <invalid loc>:80:123: TypedefDecl=__va_list_tag:80:123 [Context=TestClassForwardDecl.m]
+// CHECK-load: <invalid loc>:80:159: TypedefDecl=__builtin_va_list:80:159 [Context=TestClassForwardDecl.m]
+// CHECK-load: TestClassForwardDecl.m:10:6: FunctionDefn=function [Context=TestClassForwardDecl.m]
+// CHECK-load: TestClassForwardDecl.m:10:21: ParmDecl=arg:10:21 [Context=function]
+
diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m
new file mode 100644
index 000000000000..5427764ab7a7
--- /dev/null
+++ b/test/Index/c-index-api-loadTU-test.m
@@ -0,0 +1,224 @@
+// RUN: clang-cc -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 all | FileCheck %s
+
+// CHECK: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:0:0: StructDecl=objc_selector:0:0 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:0:0: TypedefDecl=SEL:0:0 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:0:0: ObjCInterfaceDecl=Protocol:0:0 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:0:0: TypedefDecl=id:0:0 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:0:0: TypedefDecl=Class:0:0 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:80:16: StructDecl=__va_list_tag:80:16 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:80:42: FieldDecl=gp_offset:80:42 [Context=__va_list_tag]
+// CHECK: <invalid loc>:80:63: FieldDecl=fp_offset:80:63 [Context=__va_list_tag]
+// CHECK: <invalid loc>:80:81: FieldDecl=overflow_arg_area:80:81 [Context=__va_list_tag]
+// CHECK: <invalid loc>:80:107: FieldDecl=reg_save_area:80:107 [Context=__va_list_tag]
+// CHECK: <invalid loc>:80:123: TypedefDecl=__va_list_tag:80:123 [Context=c-index-api-loadTU-test.m]
+// CHECK: <invalid loc>:80:159: TypedefDecl=__builtin_va_list:80:159 [Context=c-index-api-loadTU-test.m]
+//
+
+@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
+};
+
+// CHECK: c-index-api-loadTU-test.m:20:12: ObjCInterfaceDecl=Foo:20:1 [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:24:1: ObjCInstanceMethodDecl=foo:24:1 [Context=Foo]
+// CHECK: c-index-api-loadTU-test.m:25:1: ObjCClassMethodDecl=fooC:25:1 [Context=Foo]
+// CHECK: c-index-api-loadTU-test.m:29:12: ObjCInterfaceDecl=Bar:29:1 [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:29:18: ObjCSuperClassRef=Foo:29:1 [Context=Bar]
+// CHECK: c-index-api-loadTU-test.m:35:1: ObjCCategoryDecl=FooCat:35:1 [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:20:1: ObjCClassRef=Foo:35:1 [Context=FooCat]
+// CHECK: c-index-api-loadTU-test.m:36:1: ObjCInstanceMethodDecl=catMethodWithFloat::36:1 [Context=FooCat]
+// CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=floatMethod:37:1 [Context=FooCat]
+// CHECK: c-index-api-loadTU-test.m:40:1: ObjCProtocolDecl=Proto:40:1 [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:41:1: ObjCInstanceMethodDecl=pMethod:41:1 [Context=Proto]
+// CHECK: c-index-api-loadTU-test.m:44:1: ObjCProtocolDecl=SubP:44:1 [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:40:1: ObjCProtocolRef=Proto:40:1 [Context=SubP]
+// CHECK: c-index-api-loadTU-test.m:45:1: ObjCInstanceMethodDecl=spMethod:45:1 [Context=SubP]
+// CHECK: c-index-api-loadTU-test.m:48:12: ObjCInterfaceDecl=Baz:48:1 [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:48:18: ObjCSuperClassRef=Bar:48:1 [Context=Baz]
+// CHECK: c-index-api-loadTU-test.m:44:1: ObjCProtocolRef=SubP:44:1 [Context=Baz]
+// CHECK: c-index-api-loadTU-test.m:50:9: ObjCIvarDecl=_anIVar:50:9 [Context=Baz]
+// CHECK: c-index-api-loadTU-test.m:53:1: ObjCInstanceMethodDecl=bazMethod:53:1 [Context=Baz]
+// CHECK: c-index-api-loadTU-test.m:57:1: EnumDecl=:57:1 [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:58:3: EnumConstantDecl=someEnum:58:3 [Context=]
+
+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-loadTU-test.m:83:5: FunctionDefn=main [Context=c-index-api-loadTU-test.m]
+// CHECK: c-index-api-loadTU-test.m:83:15: ParmDecl=argc:83:15 [Context=main]
+// CHECK: c-index-api-loadTU-test.m:83:34: ParmDecl=argv:83:34 [Context=main]
+// CHECK: c-index-api-loadTU-test.m:84:8: VarDecl=bee:84:8 [Context=main]
+// CHECK: c-index-api-loadTU-test.m:85:5: VarDecl=a:85:5 [Context=main]
+// CHECK: c-index-api-loadTU-test.m:86:12: VarDecl=c:86:12 [Context=main]
+// CHECK: c-index-api-loadTU-test.m:87:13: VarDecl=d:87:13 [Context=main]
+// CHECK: c-index-api-loadTU-test.m:84:2: ObjCClassRef=Baz:84:8 [Context:Baz]
+// CHECK: c-index-api-loadTU-test.m:84:3: ObjCClassRef=Baz:84:8 [Context:Baz]
+// CHECK: c-index-api-loadTU-test.m:84:4: ObjCClassRef=Baz:84:8 [Context:Baz]
+// CHECK: c-index-api-loadTU-test.m:84:6: VarDecl=bee:84:8 [Context:bee]
+// CHECK: c-index-api-loadTU-test.m:84:8: VarDecl=bee:84:8 [Context:bee]
+// CHECK: c-index-api-loadTU-test.m:84:9: VarDecl=bee:84:8 [Context:bee]
+// CHECK: c-index-api-loadTU-test.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-loadTU-test.m:85:5: VarDecl=a:85:5 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:6: VarDecl=a:85:5 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:7: VarDecl=a:85:5 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:8: VarDecl=a:85:5 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:9: ObjCSelectorRef=foo:24:1 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:10: VarRef=bee:84:8 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:11: VarRef=bee:84:8 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:12: VarRef=bee:84:8 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:13: ObjCSelectorRef=foo:24:1 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:14: ObjCSelectorRef=foo:24:1 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:15: ObjCSelectorRef=foo:24:1 [Context:a]
+// CHECK: c-index-api-loadTU-test.m:85:16: ObjCSelectorRef=foo:24:1 [Context:a]
+// CHECK: c-index-api-loadTU-test.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-loadTU-test.m:86:5: VarDecl=c:86:12 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:6: ObjCProtocolRef=SubP:86:12 [Context:SubP]
+// CHECK: c-index-api-loadTU-test.m:86:7: ObjCProtocolRef=SubP:86:12 [Context:SubP]
+// CHECK: c-index-api-loadTU-test.m:86:8: ObjCProtocolRef=SubP:86:12 [Context:SubP]
+// CHECK: c-index-api-loadTU-test.m:86:9: ObjCProtocolRef=SubP:86:12 [Context:SubP]
+// CHECK: c-index-api-loadTU-test.m:86:10: VarDecl=c:86:12 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:12: VarDecl=c:86:12 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:13: VarDecl=c:86:12 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:14: VarDecl=c:86:12 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:15: VarDecl=c:86:12 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:16: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:17: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:18: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:19: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:20: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:21: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:22: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:23: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.m:86:24: ObjCSelectorRef=fooC:25:1 [Context:c]
+// CHECK: c-index-api-loadTU-test.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-loadTU-test.m:87:5: VarDecl=d:87:13 [Context:d]
+// CHECK: c-index-api-loadTU-test.m:87:6: ObjCProtocolRef=Proto:87:13 [Context:Proto]
+// CHECK: c-index-api-loadTU-test.m:87:7: ObjCProtocolRef=Proto:87:13 [Context:Proto]
+// CHECK: c-index-api-loadTU-test.m:87:8: ObjCProtocolRef=Proto:87:13 [Context:Proto]
+// CHECK: c-index-api-loadTU-test.m:87:9: ObjCProtocolRef=Proto:87:13 [Context:Proto]
+// CHECK: c-index-api-loadTU-test.m:87:10: ObjCProtocolRef=Proto:87:13 [Context:Proto]
+// CHECK: c-index-api-loadTU-test.m:87:11: VarDecl=d:87:13 [Context:d]
+// CHECK: c-index-api-loadTU-test.m:87:13: VarDecl=d:87:13 [Context:d]
+// CHECK: c-index-api-loadTU-test.m:88:2: VarRef=d:87:13 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:88:6: VarRef=c:86:12 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:2: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:3: VarRef=d:87:13 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:4: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:5: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:6: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:7: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:8: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:9: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:10: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:11: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:89:12: ObjCSelectorRef=pMethod:41:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:2: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:3: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:4: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:5: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:6: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:7: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:8: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:9: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:10: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:11: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:12: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:13: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:14: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:15: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:16: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:17: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:18: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:19: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:20: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:21: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:22: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:23: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:24: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:25: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:26: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:27: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:28: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:29: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:30: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:31: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:32: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:33: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:34: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:35: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:36: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:37: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:38: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:39: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:40: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:41: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:42: ObjCSelectorRef=floatMethod:37:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:90:43: ObjCSelectorRef=catMethodWithFloat::36:1 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:3: FunctionRef=main:83:5 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:4: FunctionRef=main:83:5 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:5: FunctionRef=main:83:5 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:6: FunctionRef=main:83:5 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:8: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:9: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:10: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:11: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:12: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:13: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:14: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:15: EnumConstantRef=someEnum:58:3 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:33: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:34: VarRef=bee:84:8 [Context:main]
+// CHECK: c-index-api-loadTU-test.m:91:35: VarRef=bee:84:8 [Context:main]
diff --git a/test/Index/c-index-api-test.m b/test/Index/c-index-api-test.m
index 20d4d7b45afd..55669e7579cd 100644
--- a/test/Index/c-index-api-test.m
+++ b/test/Index/c-index-api-test.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-pch -x objective-c %s -o %t.ast &&
+// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-pch -x objective-c %s -o %t.ast
// RUN: c-index-test %t.ast all | FileCheck %s
// CHECK: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 [Context=c-index-api-test.m]
diff --git a/test/Index/c-index-getCursor-test.m b/test/Index/c-index-getCursor-test.m
new file mode 100644
index 000000000000..3653a9c2e214
--- /dev/null
+++ b/test/Index/c-index-getCursor-test.m
@@ -0,0 +1,160 @@
+// RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast
+// RUN: c-index-test -test-file-scan %t.ast %s | 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: {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=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=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=1} ObjCInterfaceDecl=Foo:3:1
+// CHECK: {start_line=10 start_col=2 end_line=11 end_col=1} Invalid Cursor => NoDeclFound
+// CHECK: {start_line=12 start_col=1 end_line=16 end_col=1} ObjCInterfaceDecl=Bar:12:1
+// CHECK: {start_line=16 start_col=2 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=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=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=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=1} ObjCCategoryDecl=FooCat:18:1
+// CHECK: {start_line=21 start_col=2 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=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=1} ObjCProtocolDecl=Proto:23:1
+// CHECK: {start_line=25 start_col=2 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=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=1} ObjCProtocolDecl=SubP:27:1
+// CHECK: {start_line=29 start_col=2 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=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=1} ObjCInterfaceDecl=Baz:31:1
+// CHECK: {start_line=38 start_col=2 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
+
diff --git a/test/Index/c-index-pch.c b/test/Index/c-index-pch.c
index aae4eb3669fc..1ce108525186 100644
--- a/test/Index/c-index-pch.c
+++ b/test/Index/c-index-pch.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -emit-pch -x c -o %t.pch %S/c-index-pch.h &&
-// RUN: clang-cc -include-pch %t.pch -x c -emit-pch -o %t.ast %s &&
-// RUN: c-index-test %t.ast all | FileCheck -check-prefix=ALL %s &&
-// RUN: c-index-test %t.ast local | FileCheck -check-prefix=LOCAL %s
+// RUN: clang-cc -emit-pch -x c -o %t.pch %S/Inputs/c-index-pch.h
+// RUN: clang-cc -include-pch %t.pch -x c -emit-pch -o %t.ast %s
+// RUN: c-index-test -test-load-tu %t.ast all | FileCheck -check-prefix=ALL %s
+// RUN: c-index-test -test-load-tu %t.ast local | FileCheck -check-prefix=LOCAL %s
// ALL: FunctionDecl=foo
// ALL: VarDecl=bar
// ALL: FunctionDecl=wibble
diff --git a/test/Index/code-completion.cpp b/test/Index/code-completion.cpp
new file mode 100644
index 000000000000..44bd9d28932e
--- /dev/null
+++ b/test/Index/code-completion.cpp
@@ -0,0 +1,53 @@
+// Code-completion through the C interface
+#include "nonexistent_header.h"
+struct X {
+ int member;
+
+ enum E { Val1 };
+};
+
+struct Y {
+ float member;
+ void memfunc(int i = 17);
+};
+
+struct Z : X, Y {
+ double member;
+ operator int() const;
+};
+
+struct Z get_Z();
+
+void test_Z() {
+ // RUN: c-index-test -code-completion-at=%s:23:11 %s | FileCheck -check-prefix=CHECK-MEMBER %s
+ get_Z().member = 17;
+}
+
+
+float& overloaded(int i, long second);
+double& overloaded(float f, int second);
+int& overloaded(Z z, int second);
+
+void test_overloaded() {
+ // RUN: c-index-test -code-completion-at=%s:33:18 %s | FileCheck -check-prefix=CHECK-OVERLOAD %s
+ overloaded(Z(), 0);
+}
+
+// CHECK-MEMBER: EnumDecl:{Informative X::}{TypedText E}
+// CHECK-MEMBER: FieldDecl:{TypedText member}
+// CHECK-MEMBER: FunctionDecl:{Informative Y::}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )}
+// CHECK-MEMBER: EnumConstantDecl:{Informative E::}{TypedText Val1}
+// CHECK-MEMBER: FunctionDecl:{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )}
+// CHECK-MEMBER: FunctionDecl:{TypedText operator int}{LeftParen (}{RightParen )}
+// CHECK-MEMBER: FunctionDecl:{TypedText operator=}{LeftParen (}{Placeholder struct Z const &}{RightParen )}
+// CHECK-MEMBER: StructDecl:{TypedText X}{Text ::}
+// CHECK-MEMBER: StructDecl:{TypedText Y}{Text ::}
+// CHECK-MEMBER: StructDecl:{TypedText Z}{Text ::}
+// CHECK-MEMBER: FieldDecl:{Text X::}{TypedText member}
+// CHECK-MEMBER: FieldDecl:{Text Y::}{TypedText member}
+// CHECK-MEMBER: FunctionDecl:{Text X::}{TypedText operator=}{LeftParen (}{Placeholder struct X const &}{RightParen )}
+// CHECK-MEMBER: FunctionDecl:{Text Y::}{TypedText operator=}{LeftParen (}{Placeholder struct Y const &}{RightParen )}
+
+// CHECK-OVERLOAD: NotImplemented:{Text overloaded}{LeftParen (}{Text struct Z z}{Comma , }{CurrentParameter int second}{RightParen )}
+// CHECK-OVERLOAD: NotImplemented:{Text overloaded}{LeftParen (}{Text int i}{Comma , }{CurrentParameter long second}{RightParen )}
+// CHECK-OVERLOAD: NotImplemented:{Text overloaded}{LeftParen (}{Text float f}{Comma , }{CurrentParameter int second}{RightParen )}
diff --git a/test/Index/comments.c b/test/Index/comments.c
index 689ce88e2213..83bdbf6eed7d 100644
--- a/test/Index/comments.c
+++ b/test/Index/comments.c
@@ -19,16 +19,16 @@ void g(int);
void h(int); ///< This is a member comment.
-// RUN: clang-cc -emit-pch -o %t.ast %s &&
+// RUN: clang-cc -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: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: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: 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/complete-member-access.m b/test/Index/complete-member-access.m
new file mode 100644
index 000000000000..9202d0522f4b
--- /dev/null
+++ b/test/Index/complete-member-access.m
@@ -0,0 +1,30 @@
+/* Note: the RUN lines are near the end of the file, since line/column
+ matter for this test. */
+
+@protocol MyProtocol
+@property float ProtoProp;
+@end
+
+@interface Super {
+ int SuperIVar;
+}
+@end
+@interface Int : Super<MyProtocol>
+{
+ int IVar;
+}
+
+@property int prop1;
+@end
+
+void test_props(Int* ptr) {
+ ptr.prop1 = 0;
+ ptr->IVar = 0;
+}
+
+// RUN: c-index-test -code-completion-at=%s:21:7 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: ObjCPropertyDecl:{TypedText prop1}
+// CHECK-CC1: ObjCPropertyDecl:{TypedText ProtoProp}
+// RUN: c-index-test -code-completion-at=%s:22:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: ObjCIvarDecl:{TypedText IVar}
+// CHECK-CC2: ObjCIvarDecl:{TypedText SuperIVar}
diff --git a/test/Index/complete-objc-message.m b/test/Index/complete-objc-message.m
new file mode 100644
index 000000000000..8f235d39bec2
--- /dev/null
+++ b/test/Index/complete-objc-message.m
@@ -0,0 +1,107 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+@protocol FooTestProtocol
++ protocolClassMethod;
+- protocolInstanceMethod : (int)value;
+@end
+@interface Foo <FooTestProtocol> {
+ void *isa;
+}
++ (int)classMethod1:a withKeyword:(int)b;
++ (void)classMethod2;
++ new;
+- instanceMethod1;
+@end
+
+@interface Foo (FooTestCategory)
++ categoryClassMethod;
+- categoryInstanceMethod;
+@end
+
+void func() {
+ Foo *obj = [Foo new];
+ [obj xx];
+}
+
+@interface MyClass { }
++ (int)MyClassMethod:(id)obj;
+- (int)MyInstMethod:(id)x second:(id)y;
+@end
+
+@interface MySubClass : MyClass { }
++ (int)MySubClassMethod;
+- (int)MySubInstMethod;
+@end
+
+@implementation MyClass
++ (int)MyClassMethod:(id)obj {
+ return 0;
+}
+
++ (int)MyPrivateMethod {
+ return 1;
+}
+
+- (int)MyInstMethod:(id)x second:(id)y {
+ return 2;
+}
+
+- (int)MyPrivateInstMethod {
+ return 3;
+}
+@end
+
+@implementation MySubClass
++ (int)MySubClassMethod {
+ return 2;
+}
+
++ (int)MySubPrivateMethod {
+ return [super MyPrivateMethod];
+}
+
+- (int)MySubInstMethod:(id)obj {
+ return [super MyInstMethod: obj second:obj];
+}
+
+- (int)MyInstMethod:(id)x second:(id)y {
+ return 3;
+}
+@end
+
+void test_super_var(MySubClass *super) {
+ [super MyInstMethod: super second:super];
+}
+
+@protocol FooTestProtocol2
+- (int)secondProtocolInstanceMethod;
+@end
+
+void test_qual_id(id<FooTestProtocol,FooTestProtocol2> ptr) {
+ [ptr protocolInstanceMethod:1];
+}
+
+// RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: {TypedText categoryClassMethod}
+// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)a}{Text withKeyword:}{Placeholder (int)b}
+// CHECK-CC1: {TypedText classMethod2}
+// CHECK-CC1: {TypedText new}
+// CHECK-CC1: {TypedText protocolClassMethod}
+// RUN: c-index-test -code-completion-at=%s:24:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: {TypedText categoryInstanceMethod}
+// CHECK-CC2: {TypedText instanceMethod1}
+// CHECK-CC2: {TypedText protocolInstanceMethod:}{Placeholder (int)value}
+// RUN: c-index-test -code-completion-at=%s:61:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: ObjCClassMethodDecl:{TypedText MyClassMethod:}{Placeholder (id)obj}
+// CHECK-CC3: ObjCClassMethodDecl:{TypedText MyPrivateMethod}
+// RUN: c-index-test -code-completion-at=%s:65:16 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: ObjCInstanceMethodDecl:{TypedText MyInstMethod:}{Placeholder (id)x}{Text second:}{Placeholder (id)y}
+// CHECK-CC4: ObjCInstanceMethodDecl:{TypedText MyPrivateInstMethod}
+// RUN: c-index-test -code-completion-at=%s:74:9 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText MyInstMethod:}{Placeholder (id)x}{Text second:}{Placeholder (id)y}
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText MySubInstMethod}
+// RUN: c-index-test -code-completion-at=%s:82:8 %s | FileCheck -check-prefix=CHECK-CC6 %s
+// CHECK-CC6: ObjCInstanceMethodDecl:{TypedText protocolInstanceMethod:}{Placeholder (int)value}
+// CHECK-CC6: ObjCInstanceMethodDecl:{TypedText secondProtocolInstanceMethod}
+
diff --git a/test/Index/complete-protocols.m b/test/Index/complete-protocols.m
new file mode 100644
index 000000000000..89f61bcf9ac9
--- /dev/null
+++ b/test/Index/complete-protocols.m
@@ -0,0 +1,25 @@
+/* Note: the RUN lines are near the end of the file, since line/column
+ matter for this test. */
+
+@protocol Protocol1
+@end
+
+@protocol Protocol2;
+
+void f(id<Protocol1,Protocol2>);
+
+@protocol Protocol0;
+@protocol NewProtocol
+{
+}
+@end
+
+// RUN: c-index-test -code-completion-at=%s:9:11 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: ObjCProtocolDecl:{TypedText Protocol1}
+// CHECK-CC1: ObjCProtocolDecl:{TypedText Protocol2}
+// RUN: c-index-test -code-completion-at=%s:9:21 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2-NOT: ObjCProtocolDecl:{TypedText Protocol1}
+// CHECK-CC2: ObjCProtocolDecl:{TypedText Protocol2}
+// RUN: c-index-test -code-completion-at=%s:12:11 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: ObjCProtocolDecl:{TypedText Protocol0}
+// CHECK-CC3-NEXT: ObjCProtocolDecl:{TypedText Protocol2}
diff --git a/test/Index/find-decls.c b/test/Index/find-decls.c
index 50a233d75ba5..99a32428005b 100644
--- a/test/Index/find-decls.c
+++ b/test/Index/find-decls.c
@@ -1,25 +1,25 @@
-// RUN: clang-cc -fblocks -emit-pch %S/t1.c -o %t1.ast &&
-// RUN: clang-cc -fblocks -emit-pch %S/t2.c -o %t2.ast &&
+// RUN: clang-cc -fblocks -emit-pch %S/Inputs/t1.c -o %t1.ast
+// RUN: clang-cc -fblocks -emit-pch %S/Inputs/t2.c -o %t2.ast
-// RUN: index-test %t1.ast %t2.ast -point-at %S/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: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/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: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/t1.c:6:20 -print-decls > %t &&
-// RUN: cat %t | count 1 &&
-// RUN: grep 't1.c:3:19,' %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/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: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/t1.c:22:21 -print-decls > %t &&
-// RUN: cat %t | count 1 &&
+// 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
index 0e63ae760047..fb540727341a 100644
--- a/test/Index/find-defs.c
+++ b/test/Index/find-defs.c
@@ -1,18 +1,18 @@
-// RUN: clang-cc -fblocks -emit-pch %S/t1.c -o %t1.ast &&
-// RUN: clang-cc -fblocks -emit-pch %S/t2.c -o %t2.ast &&
+// RUN: clang-cc -fblocks -emit-pch %S/Inputs/t1.c -o %t1.ast
+// RUN: clang-cc -fblocks -emit-pch %S/Inputs/t2.c -o %t2.ast
-// RUN: index-test %t1.ast %t2.ast -point-at %S/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: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/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: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/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/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/t1.c:8:7 -print-defs > %t &&
-// RUN: cat %t | count 1 &&
+// 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
index 1b58b3752773..5209e141b629 100644
--- a/test/Index/find-refs.c
+++ b/test/Index/find-refs.c
@@ -1,47 +1,47 @@
-// RUN: clang-cc -fblocks -emit-pch %S/t1.c -o %t1.ast &&
-// RUN: clang-cc -fblocks -emit-pch %S/t2.c -o %t2.ast &&
-
-// RUN: index-test %t1.ast %t2.ast -point-at %S/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/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/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/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/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/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 &&
+// RUN: clang-cc -fblocks -emit-pch %S/Inputs/t1.c -o %t1.ast
+// RUN: clang-cc -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/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: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/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/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/foo.h:7:11 -print-refs > %t &&
-// RUN: cat %t | count 2 &&
-// RUN: grep 't1.c:25: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/multiple-redecls.c b/test/Index/multiple-redecls.c
index 6f1f75b02f39..ea6d00b6a3c4 100644
--- a/test/Index/multiple-redecls.c
+++ b/test/Index/multiple-redecls.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -emit-pch %s -o %t.ast &&
-// RUN: index-test %t.ast -point-at %s:8:4 -print-decls | count 2 &&
+// RUN: clang-cc -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);
diff --git a/test/Index/objc-decls.m b/test/Index/objc-decls.m
index 1a8ab4b5577e..ff396788771d 100644
--- a/test/Index/objc-decls.m
+++ b/test/Index/objc-decls.m
@@ -1,16 +1,16 @@
-// RUN: clang-cc -emit-pch %S/t1.m -o %t1.m.ast &&
-// RUN: clang-cc -emit-pch %S/t2.m -o %t2.m.ast &&
+// RUN: clang-cc -emit-pch %S/Inputs/t1.m -o %t1.m.ast
+// RUN: clang-cc -emit-pch %S/Inputs/t2.m -o %t2.m.ast
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/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/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/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: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/objc.h:10:13 -print-decls > %t &&
-// RUN: cat %t | count 3 &&
-// RUN: grep 'objc.h:10:1,' %t | count 2 &&
+// 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
index 45ce83876cfe..de61278af87e 100644
--- a/test/Index/objc-message.m
+++ b/test/Index/objc-message.m
@@ -1,38 +1,38 @@
-// RUN: clang-cc -emit-pch %S/t1.m -o %t1.m.ast &&
-// RUN: clang-cc -emit-pch %S/t2.m -o %t2.m.ast &&
+// RUN: clang-cc -emit-pch %S/Inputs/t1.m -o %t1.m.ast
+// RUN: clang-cc -emit-pch %S/Inputs/t2.m -o %t2.m.ast
-// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/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: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/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: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/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/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/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: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/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 %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/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: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/t2.m:7:15 -print-decls > %t &&
-// RUN: cat %t | count 3 &&
-// RUN: grep 'objc.h:6:1,' %t | count 2 &&
+// 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/resolve-loc.c b/test/Index/resolve-loc.c
index cae86f38dd6d..f4697171ee18 100644
--- a/test/Index/resolve-loc.c
+++ b/test/Index/resolve-loc.c
@@ -16,22 +16,22 @@ struct S {
};
-// RUN: clang-cc -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 &&
+// RUN: clang-cc -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/block_cmt_end.c b/test/Lexer/block_cmt_end.c
index 83d6cf189243..5efb77e3cc38 100644
--- a/test/Lexer/block_cmt_end.c
+++ b/test/Lexer/block_cmt_end.c
@@ -1,8 +1,8 @@
/*
- RUN: clang-cc -E -trigraphs %s | grep bar &&
- RUN: clang-cc -E -trigraphs %s | grep foo &&
- RUN: clang-cc -E -trigraphs %s | not grep abc &&
- RUN: clang-cc -E -trigraphs %s | not grep xyz &&
+ RUN: clang-cc -E -trigraphs %s | grep bar
+ RUN: clang-cc -E -trigraphs %s | grep foo
+ RUN: clang-cc -E -trigraphs %s | not grep abc
+ RUN: clang-cc -E -trigraphs %s | not grep xyz
RUN: clang-cc -fsyntax-only -trigraphs -verify %s
*/
diff --git a/test/Lexer/counter.c b/test/Lexer/counter.c
index 9b2c2c7434f4..044570f88869 100644
--- a/test/Lexer/counter.c
+++ b/test/Lexer/counter.c
@@ -1,16 +1,16 @@
// __COUNTER__ support: rdar://4329310
-// RUN: clang -E %s > %t &&
+// RUN: clang -E %s > %t
#define PASTE2(x,y) x##y
#define PASTE1(x,y) PASTE2(x,y)
#define UNIQUE(x) PASTE1(x,__COUNTER__)
-// RUN: grep "A: 0" %t &&
+// RUN: grep "A: 0" %t
A: __COUNTER__
-// RUN: grep "B: foo1" %t &&
+// RUN: grep "B: foo1" %t
B: UNIQUE(foo);
-// RUN: grep "C: foo2" %t &&
+// RUN: grep "C: foo2" %t
C: UNIQUE(foo);
// RUN: grep "D: 3" %t
D: __COUNTER__
diff --git a/test/Lexer/digraph.c b/test/Lexer/digraph.c
index 4d494ca1dd94..3c92db1c02b2 100644
--- a/test/Lexer/digraph.c
+++ b/test/Lexer/digraph.c
@@ -1,6 +1,6 @@
// RUN: clang-cc -fsyntax-only -verify < %s
-%:include <stdio.h>
+%:include <stdint.h>
%:ifndef BUFSIZE
%:define BUFSIZE 512
diff --git a/test/Lexer/dollar-idents.c b/test/Lexer/dollar-idents.c
index f5c33b1f4368..276545d160a1 100644
--- a/test/Lexer/dollar-idents.c
+++ b/test/Lexer/dollar-idents.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -dump-tokens %s 2> %t &&
-// RUN: grep "identifier '\$A'" %t &&
-// RUN: clang-cc -dump-tokens -x assembler-with-cpp %s 2> %t &&
+// RUN: clang-cc -dump-tokens %s 2> %t
+// RUN: grep "identifier '\$A'" %t
+// RUN: clang-cc -dump-tokens -x assembler-with-cpp %s 2> %t
// RUN: grep "identifier 'A'" %t
// PR3808
diff --git a/test/Lexer/escape_newline.c b/test/Lexer/escape_newline.c
index ce120ed7c828..d07f0450ebbe 100644
--- a/test/Lexer/escape_newline.c
+++ b/test/Lexer/escape_newline.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -E -trigraphs %s | grep -- ' ->' &&
-// RUN: clang-cc -E -trigraphs %s 2>&1 | grep 'backslash and newline separated by space' &&
+// RUN: clang-cc -E -trigraphs %s | grep -- ' ->'
+// RUN: clang-cc -E -trigraphs %s 2>&1 | grep 'backslash and newline separated by space'
// RUN: clang-cc -E -trigraphs %s 2>&1 | grep 'trigraph converted'
// This is an ugly way to spell a -> token.
diff --git a/test/Lexer/rdr-6096838.c b/test/Lexer/rdr-6096838.c
index 60e5244646ad..6a8899af95bd 100644
--- a/test/Lexer/rdr-6096838.c
+++ b/test/Lexer/rdr-6096838.c
@@ -1,4 +1,4 @@
-/* RUN: clang-cc -fsyntax-only -verify %s &&
+/* RUN: clang-cc -fsyntax-only -verify %s
* RUN: clang-cc -std=gnu89 -fsyntax-only -verify %s
rdar://6096838
*/
diff --git a/test/Lexer/token-concat.c b/test/Lexer/token-concat.c
index 4e27d5d723e2..9194932b1bed 100644
--- a/test/Lexer/token-concat.c
+++ b/test/Lexer/token-concat.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -E -x c -o %t %s &&
+// RUN: clang-cc -E -x c -o %t %s
// RUN: grep 'IDENT.2' %t
IDENT.2
diff --git a/test/Misc/caret-diags-macros.c b/test/Misc/caret-diags-macros.c
index 58d293fb043e..fd3c6170ec3c 100644
--- a/test/Misc/caret-diags-macros.c
+++ b/test/Misc/caret-diags-macros.c
@@ -1,22 +1,22 @@
-// RUN: clang-cc -fsyntax-only %s > %t 2>&1 &&
+// RUN: clang-cc -fsyntax-only %s > %t 2>&1
#define M1(x) x
-// RUN: grep ":6:12: note: instantiated from:" %t &&
+// RUN: grep ":6:12: note: instantiated from:" %t
#define M2 1;
void foo() {
- // RUN: grep ":10:2: warning: expression result unused" %t &&
+ // RUN: grep ":10:2: warning: expression result unused" %t
M1(
- // RUN: grep ":12:5: note: instantiated from:" %t &&
+ // RUN: grep ":12:5: note: instantiated from:" %t
M2)
}
-// RUN: grep ":16:11: note: instantiated from:" %t &&
+// RUN: grep ":16:11: note: instantiated from:" %t
#define A 1
-// RUN: grep ":18:11: note: instantiated from:" %t &&
+// RUN: grep ":18:11: note: instantiated from:" %t
#define B A
-// RUN: grep ":20:11: note: instantiated from:" %t &&
+// RUN: grep ":20:11: note: instantiated from:" %t
#define C B
void bar() {
diff --git a/test/Misc/diag-mapping.c b/test/Misc/diag-mapping.c
index dc07e0d092b5..5816cf5ca16d 100644
--- a/test/Misc/diag-mapping.c
+++ b/test/Misc/diag-mapping.c
@@ -1,25 +1,25 @@
// This should warn by default.
-// RUN: clang-cc %s 2>&1 | grep "warning:" &&
+// RUN: clang-cc %s 2>&1 | grep "warning:"
// This should not emit anything.
-// RUN: clang-cc %s -Wno-extra-tokens 2>&1 | not grep diagnostic &&
+// RUN: clang-cc %s -Wno-extra-tokens 2>&1 | not grep diagnostic
// -Werror can map all warnings to error.
-// RUN: clang-cc %s -Werror 2>&1 | grep "error:" &&
+// RUN: clang-cc %s -Werror 2>&1 | grep "error:"
// -Werror can map this one warning to error.
-// RUN: clang-cc %s -Werror=extra-tokens 2>&1 | grep "error:" &&
+// RUN: clang-cc %s -Werror=extra-tokens 2>&1 | grep "error:"
// Mapping unrelated diags to errors doesn't affect this one.
-// RUN: clang-cc %s -Werror=trigraphs 2>&1 | grep "warning:" &&
+// RUN: clang-cc %s -Werror=trigraphs 2>&1 | grep "warning:"
// This should stay a warning with -pedantic.
-// RUN: clang-cc %s -pedantic 2>&1 | grep "warning:" &&
+// RUN: clang-cc %s -pedantic 2>&1 | grep "warning:"
// This should emit an error with -pedantic-errors.
-// RUN: clang-cc %s -pedantic-errors 2>&1 | grep "error:" &&
+// RUN: clang-cc %s -pedantic-errors 2>&1 | grep "error:"
// This should emit a warning, because -Wfoo overrides -pedantic*.
-// RUN: clang-cc %s -pedantic-errors -Wextra-tokens 2>&1 | grep "warning:" &&
+// RUN: clang-cc %s -pedantic-errors -Wextra-tokens 2>&1 | grep "warning:"
// This should emit nothing, because -Wno-extra-tokens overrides -pedantic*
// RUN: clang-cc %s -pedantic-errors -Wno-extra-tokens 2>&1 | not grep diagnostic
diff --git a/test/Misc/diag-mapping2.c b/test/Misc/diag-mapping2.c
index c5fd7fff81f6..cde90e299a04 100644
--- a/test/Misc/diag-mapping2.c
+++ b/test/Misc/diag-mapping2.c
@@ -1,18 +1,18 @@
// This should warn by default.
-// RUN: clang-cc %s 2>&1 | grep "warning:" &&
+// RUN: clang-cc %s 2>&1 | grep "warning:"
// This should not emit anything.
-// RUN: clang-cc %s -w 2>&1 | not grep diagnostic &&
-// RUN: clang-cc %s -Wno-#warnings 2>&1 | not grep diagnostic &&
+// RUN: clang-cc %s -w 2>&1 | not grep diagnostic
+// RUN: clang-cc %s -Wno-#warnings 2>&1 | not grep diagnostic
// -Werror can map all warnings to error.
-// RUN: clang-cc %s -Werror 2>&1 | grep "error:" &&
+// RUN: clang-cc %s -Werror 2>&1 | grep "error:"
// -Werror can map this one warning to error.
-// RUN: clang-cc %s -Werror=#warnings 2>&1 | grep "error:" &&
+// RUN: clang-cc %s -Werror=#warnings 2>&1 | grep "error:"
// -Wno-error= overrides -Werror. rdar://3158301
-// RUN: clang-cc %s -Werror -Wno-error=#warnings 2>&1 | grep "warning:" &&
+// RUN: clang-cc %s -Werror -Wno-error=#warnings 2>&1 | grep "warning:"
// -Wno-error overrides -Werror. PR4715
// RUN: clang-cc %s -Werror -Wno-error 2>&1 | grep "warning:"
diff --git a/test/Misc/message-length.c b/test/Misc/message-length.c
index 4502951dbf62..841ffc9f615d 100644
--- a/test/Misc/message-length.c
+++ b/test/Misc/message-length.c
@@ -1,4 +1,4 @@
-// RUN: clang -fsyntax-only -fmessage-length=72 %s 2>&1 | FileCheck -strict-whitespace %s &&
+// RUN: clang -fsyntax-only -fmessage-length=72 %s 2>&1 | FileCheck -strict-whitespace %s
// RUN: clang -fsyntax-only -fmessage-length=1 %s
// Hack so we can check things better, force the file name and line.
diff --git a/test/PCH/asm.c b/test/PCH/asm.c
index bff271de0390..61665d607f41 100644
--- a/test/PCH/asm.c
+++ b/test/PCH/asm.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -triple i386-unknown-unknown -include %S/asm.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -triple i386-unknown-unknown -include %S/asm.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -triple i386-unknown-unknown -emit-pch -o %t %S/asm.h &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-pch -o %t %S/asm.h
// RUN: clang-cc -triple i386-unknown-unknown -include-pch %t -fsyntax-only -verify %s
diff --git a/test/PCH/attrs.c b/test/PCH/attrs.c
index 1ffb467f63db..f381f2370406 100644
--- a/test/PCH/attrs.c
+++ b/test/PCH/attrs.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/attrs.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/attrs.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/attrs.h &&
+// RUN: clang-cc -emit-pch -o %t %S/attrs.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
// expected-note{{previous overload}}
double f(double); // expected-error{{overloadable}}
diff --git a/test/PCH/blocks.c b/test/PCH/blocks.c
index f3efc8ac4bcc..ccecd3652350 100644
--- a/test/PCH/blocks.c
+++ b/test/PCH/blocks.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -fblocks -include %S/blocks.h -fsyntax-only -emit-llvm -o - %s &&
+// RUN: clang-cc -fblocks -include %S/blocks.h -fsyntax-only -emit-llvm -o - %s
// Test with pch.
-// RUN: clang-cc -emit-pch -fblocks -o %t %S/blocks.h &&
+// RUN: clang-cc -emit-pch -fblocks -o %t %S/blocks.h
// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -emit-llvm -o - %s
int do_add(int x, int y) { return add(x, y); }
diff --git a/test/PCH/builtins.c b/test/PCH/builtins.c
index 3d1786ba7713..796b9dcda12c 100644
--- a/test/PCH/builtins.c
+++ b/test/PCH/builtins.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/builtins.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/builtins.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/builtins.h &&
+// RUN: clang-cc -emit-pch -o %t %S/builtins.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
void hello() {
diff --git a/test/PCH/enum.c b/test/PCH/enum.c
index 45b0491c6f53..607de59a8aea 100644
--- a/test/PCH/enum.c
+++ b/test/PCH/enum.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/enum.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/enum.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/enum.h &&
+// RUN: clang-cc -emit-pch -o %t %S/enum.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
int i = Red;
diff --git a/test/PCH/exprs.c b/test/PCH/exprs.c
index c8e6d1dc3030..6cd1ee71b4c3 100644
--- a/test/PCH/exprs.c
+++ b/test/PCH/exprs.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -fblocks -include %S/exprs.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -fblocks -include %S/exprs.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -fblocks -o %t %S/exprs.h &&
+// RUN: clang-cc -emit-pch -fblocks -o %t %S/exprs.h
// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s
int integer;
diff --git a/test/PCH/ext_vector.c b/test/PCH/ext_vector.c
index 4b5c25980e56..314dbfcf1692 100644
--- a/test/PCH/ext_vector.c
+++ b/test/PCH/ext_vector.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/ext_vector.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/ext_vector.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/ext_vector.h &&
+// RUN: clang-cc -emit-pch -o %t %S/ext_vector.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
int test(float4 f4) {
diff --git a/test/PCH/external-defs.c b/test/PCH/external-defs.c
index b7eb700e6b3e..447124cc3f78 100644
--- a/test/PCH/external-defs.c
+++ b/test/PCH/external-defs.c
@@ -1,15 +1,15 @@
// Test with pch.
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-pch -o %t.pch %S/external-defs.h &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-pch -o %t.pch %S/external-defs.h
+// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s
-// RUN: grep "@x = common global i32 0" %t | count 1 &&
-// RUN: grep "@z" %t | count 0 &&
+// RUN: grep "@x = common global i32 0" %t | count 1
+// RUN: grep "@z" %t | count 0
-// RUN: grep "@x2 = global i32 19" %t | count 1 &&
+// RUN: grep "@x2 = global i32 19" %t | count 1
int x2 = 19;
-// RUN: grep "@incomplete_array = common global .*1 x i32" %t | count 1 &&
-// RUN: grep "@incomplete_array2 = common global .*17 x i32" %t | count 1 &&
+// RUN: grep "@incomplete_array = common global .*1 x i32" %t | count 1
+// RUN: grep "@incomplete_array2 = common global .*17 x i32" %t | count 1
int incomplete_array2[17];
// RUN: grep "@incomplete_array3 = common global .*1 x i32" %t | count 1
int incomplete_array3[];
diff --git a/test/PCH/functions.c b/test/PCH/functions.c
index 6d3c5a0f7b81..2121b9aaa107 100644
--- a/test/PCH/functions.c
+++ b/test/PCH/functions.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/functions.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/functions.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/functions.h &&
+// RUN: clang-cc -emit-pch -o %t %S/functions.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
int f0(int x0, int y0, ...) { return x0 + y0; }
diff --git a/test/PCH/fuzzy-pch.c b/test/PCH/fuzzy-pch.c
index 2ddcb8bb089b..b29638bb0b10 100644
--- a/test/PCH/fuzzy-pch.c
+++ b/test/PCH/fuzzy-pch.c
@@ -1,7 +1,7 @@
// Test with pch.
-// RUN: clang-cc -emit-pch -DFOO -o %t %S/variables.h &&
-// RUN: clang-cc -DBAR=int -include-pch %t -fsyntax-only -pedantic %s &&
-// RUN: clang-cc -DFOO -DBAR=int -include-pch %t -Werror %s &&
+// RUN: clang-cc -emit-pch -DFOO -o %t %S/variables.h
+// RUN: clang-cc -DBAR=int -include-pch %t -fsyntax-only -pedantic %s
+// RUN: clang-cc -DFOO -DBAR=int -include-pch %t -Werror %s
// RUN: not clang-cc -DFOO -DBAR=int -DX=5 -include-pch %t -Werror %s
BAR bar = 17;
diff --git a/test/PCH/line-directive.c b/test/PCH/line-directive.c
index 53edb3c06b8c..9eed4f4a9823 100644
--- a/test/PCH/line-directive.c
+++ b/test/PCH/line-directive.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/line-directive.h -fsyntax-only %s 2>&1|grep "25:5" &&
+// RUN: clang-cc -include %S/line-directive.h -fsyntax-only %s 2>&1|grep "25:5"
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/line-directive.h &&
+// RUN: clang-cc -emit-pch -o %t %S/line-directive.h
// RUN: clang-cc -include-pch %t -fsyntax-only %s 2>&1|grep "25:5"
double x; // expected-error{{redefinition of 'x' with a different type}}
diff --git a/test/PCH/method_pool.m b/test/PCH/method_pool.m
index 8dd7834f1dab..3fe45a66a47d 100644
--- a/test/PCH/method_pool.m
+++ b/test/PCH/method_pool.m
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/method_pool.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/method_pool.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/method_pool.h &&
+// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/method_pool.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
int message_id(id x) {
diff --git a/test/PCH/multiple_decls.c b/test/PCH/multiple_decls.c
index 4b2fc6247ce7..2702cd61bba6 100644
--- a/test/PCH/multiple_decls.c
+++ b/test/PCH/multiple_decls.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/multiple_decls.h -fsyntax-only -ast-print -o - %s &&
+// RUN: clang-cc -include %S/multiple_decls.h -fsyntax-only -ast-print -o - %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/multiple_decls.h &&
+// RUN: clang-cc -emit-pch -o %t %S/multiple_decls.h
// RUN: clang-cc -include-pch %t -fsyntax-only -ast-print -o - %s
void f0(char c) {
diff --git a/test/PCH/nonvisible-external-defs.c b/test/PCH/nonvisible-external-defs.c
index bfe5ccab20a3..a78674985c98 100644
--- a/test/PCH/nonvisible-external-defs.c
+++ b/test/PCH/nonvisible-external-defs.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/nonvisible-external-defs.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/nonvisible-external-defs.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/nonvisible-external-defs.h &&
+// RUN: clang-cc -emit-pch -o %t %S/nonvisible-external-defs.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
int g(int, float); // expected-error{{conflicting types}}
diff --git a/test/PCH/objc_exprs.m b/test/PCH/objc_exprs.m
index 48966f36f33a..9eb5a113a247 100644
--- a/test/PCH/objc_exprs.m
+++ b/test/PCH/objc_exprs.m
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -fblocks -include %S/objc_exprs.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -fblocks -include %S/objc_exprs.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -x objective-c-header -emit-pch -fblocks -o %t %S/objc_exprs.h &&
+// RUN: clang-cc -x objective-c-header -emit-pch -fblocks -o %t %S/objc_exprs.h
// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s
// Expressions
diff --git a/test/PCH/objc_import.m b/test/PCH/objc_import.m
index 86c1c25ae5c9..83f389c4ca90 100644
--- a/test/PCH/objc_import.m
+++ b/test/PCH/objc_import.m
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/objc_import.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/objc_import.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_import.h &&
+// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_import.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
#import "objc_import.h"
diff --git a/test/PCH/objc_methods.m b/test/PCH/objc_methods.m
index 1a198b18d380..aff34d114f02 100644
--- a/test/PCH/objc_methods.m
+++ b/test/PCH/objc_methods.m
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/objc_methods.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/objc_methods.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_methods.h &&
+// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_methods.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
void func() {
diff --git a/test/PCH/objc_property.m b/test/PCH/objc_property.m
index 5cf6de759375..a1d3eb99ceb5 100644
--- a/test/PCH/objc_property.m
+++ b/test/PCH/objc_property.m
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/objc_property.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/objc_property.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_property.h &&
+// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_property.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
void func() {
diff --git a/test/PCH/pr4489.c b/test/PCH/pr4489.c
index d05d5cd7ddab..aaf5aac749e5 100644
--- a/test/PCH/pr4489.c
+++ b/test/PCH/pr4489.c
@@ -1,5 +1,5 @@
-// RUN: clang -x c-header -o %t.pch %s &&
-// RUN: echo > %t.empty.c &&
+// RUN: clang -x c-header -o %t.pch %s
+// RUN: echo > %t.empty.c
// RUN: clang -include %t -x c %t.empty.c -emit-llvm -S -o -
// PR 4489: Crash with PCH
// PR 4492: Crash with PCH (round two)
diff --git a/test/PCH/preprocess.c b/test/PCH/preprocess.c
index 128cc0acb973..7a6c2c5a4e2b 100644
--- a/test/PCH/preprocess.c
+++ b/test/PCH/preprocess.c
@@ -1,5 +1,8 @@
-// RUN: clang-cc -emit-pch -o %t %S/preprocess.h &&
-// RUN: clang-cc -include-pch %t -E -o - %s | grep -c "a_typedef" | count 1
-#include "preprocess.h"
+// Check that -E mode is invariant when using an implicit PCH.
-int a_value;
+// RUN: clang-cc -include %S/preprocess.h -E -o %t.orig %s
+// RUN: clang-cc -emit-pch -o %t %S/preprocess.h
+// RUN: clang-cc -include-pch %t -E -o %t.from_pch %s
+// RUN: diff %t.orig %t.from_pch
+
+a_typedef a_value;
diff --git a/test/PCH/reloc.c b/test/PCH/reloc.c
index b08187fdb8d8..36247d50296e 100644
--- a/test/PCH/reloc.c
+++ b/test/PCH/reloc.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -emit-pch -o %t --relocatable-pch -isysroot %S/libroot %S/libroot/usr/include/reloc.h &&
-// RUN: clang-cc -include-pch %t -isysroot %S/libroot %s -verify &&
+// RUN: clang-cc -emit-pch -o %t --relocatable-pch -isysroot %S/libroot %S/libroot/usr/include/reloc.h
+// RUN: clang-cc -include-pch %t -isysroot %S/libroot %s -verify
// RUN: not clang-cc -include-pch %t %s
#include <reloc.h>
diff --git a/test/PCH/stmts.c b/test/PCH/stmts.c
index 0d906f291f2c..69c7ec7dbf49 100644
--- a/test/PCH/stmts.c
+++ b/test/PCH/stmts.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/stmts.h -fsyntax-only -emit-llvm -o - %s &&
+// RUN: clang-cc -include %S/stmts.h -fsyntax-only -emit-llvm -o - %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/stmts.h &&
+// RUN: clang-cc -emit-pch -o %t %S/stmts.h
// RUN: clang-cc -include-pch %t -fsyntax-only -emit-llvm -o - %s
void g0(void) { f0(5); }
diff --git a/test/PCH/struct.c b/test/PCH/struct.c
index f1e28115d0d7..6595a2fbdccc 100644
--- a/test/PCH/struct.c
+++ b/test/PCH/struct.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/struct.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/struct.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/struct.h &&
+// RUN: clang-cc -emit-pch -o %t %S/struct.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
struct Point *p1;
diff --git a/test/PCH/tentative-defs.c b/test/PCH/tentative-defs.c
index 980cfab0834b..5b85fccbcacd 100644
--- a/test/PCH/tentative-defs.c
+++ b/test/PCH/tentative-defs.c
@@ -1,8 +1,8 @@
// Test with pch.
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-pch -o %t.pch %S/tentative-defs.h &&
-// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -verify -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-pch -o %t.pch %S/tentative-defs.h
+// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -verify -emit-llvm -o %t %s
-// RUN: grep "@variable = common global i32 0" %t | count 1 &&
+// RUN: grep "@variable = common global i32 0" %t | count 1
// RUN: grep "@incomplete_array = common global .*1 x i32" %t | count 1
diff --git a/test/PCH/types.c b/test/PCH/types.c
index c111c9ea7459..a7efaef9a2c4 100644
--- a/test/PCH/types.c
+++ b/test/PCH/types.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -fblocks -include %S/types.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -fblocks -include %S/types.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -fblocks -o %t %S/types.h &&
+// RUN: clang-cc -emit-pch -fblocks -o %t %S/types.h
// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s
typedef int INT;
diff --git a/test/PCH/va_arg.c b/test/PCH/va_arg.c
index 75cee06d656f..6f7ccf456185 100644
--- a/test/PCH/va_arg.c
+++ b/test/PCH/va_arg.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -include %S/va_arg.h %s -emit-llvm -o - &&
+// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -include %S/va_arg.h %s -emit-llvm -o -
// Test with pch.
-// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -emit-pch -o %t %S/va_arg.h &&
+// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -emit-pch -o %t %S/va_arg.h
// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -include-pch %t %s -emit-llvm -o -
char *g0(char** argv, int argc) { return argv[argc]; }
diff --git a/test/PCH/variables.c b/test/PCH/variables.c
index c988a59ce605..f79b68483fd9 100644
--- a/test/PCH/variables.c
+++ b/test/PCH/variables.c
@@ -1,8 +1,8 @@
// Test this without pch.
-// RUN: clang-cc -include %S/variables.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/variables.h -fsyntax-only -verify %s
// Test with pch.
-// RUN: clang-cc -emit-pch -o %t %S/variables.h &&
+// RUN: clang-cc -emit-pch -o %t %S/variables.h
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
int *ip2 = &x;
diff --git a/test/Parser/2008-10-31-parse-noop-failure.c b/test/Parser/2008-10-31-parse-noop-failure.c
index 0598ea7dc9e7..8243cb973105 100755
--- a/test/Parser/2008-10-31-parse-noop-failure.c
+++ b/test/Parser/2008-10-31-parse-noop-failure.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -verify -parse-noop %t
+// RUN: clang-cc -verify -parse-noop %s
void add_attribute(id) int id; {}
diff --git a/test/Parser/block-block-storageclass.c b/test/Parser/block-block-storageclass.c
index d24ec5f1c698..df9423460cd5 100644
--- a/test/Parser/block-block-storageclass.c
+++ b/test/Parser/block-block-storageclass.c
@@ -1,6 +1,6 @@
// RUN: clang-cc -fsyntax-only -verify -parse-noop %s
#if 0
-#include <stdio.h>
+int printf(const char *, ...);
void _Block_byref_release(void*src){}
int main() {
diff --git a/test/Parser/control-scope.c b/test/Parser/control-scope.c
index 7ffc6ac46c0f..8c4e19965edb 100644
--- a/test/Parser/control-scope.c
+++ b/test/Parser/control-scope.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -std=c90 -verify &&
+// RUN: clang-cc %s -std=c90 -verify
// RUN: clang-cc %s -std=c99
int f (int z) {
diff --git a/test/Parser/cxx-using-declaration.cpp b/test/Parser/cxx-using-declaration.cpp
index 212a7d89f877..a2bc8c54edc7 100644
--- a/test/Parser/cxx-using-declaration.cpp
+++ b/test/Parser/cxx-using-declaration.cpp
@@ -1,6 +1,6 @@
// FIXME: Disabled, appears to have undefined behavior, and needs to be updated to match new warnings.
-// RUN: true
-// RUNX: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL: *
namespace A {
int VA;
diff --git a/test/Parser/objc-init.m b/test/Parser/objc-init.m
index a91ac9cf285b..bc88e33e3720 100644
--- a/test/Parser/objc-init.m
+++ b/test/Parser/objc-init.m
@@ -39,3 +39,21 @@ void test5(NSNumber *x) {
.x [x METH2] // expected-error {{expected '=' or another designator}}
};
}
+
+// rdar://7370882
+@interface SemicolonsAppDelegate
+{
+ id i;
+}
+@property (assign) id window;
+@end
+
+@implementation SemicolonsAppDelegate
+{
+ id i;
+}
+ @synthesize window=i;
+@end
+
+
+
diff --git a/test/Parser/objc-try-catch-1.m b/test/Parser/objc-try-catch-1.m
index a8d37f0ab959..98c6d16ff698 100644
--- a/test/Parser/objc-try-catch-1.m
+++ b/test/Parser/objc-try-catch-1.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s &&
+// RUN: clang-cc -fsyntax-only -verify %s
// RUN: clang-cc -fsyntax-only -verify -x objective-c++ %s
void * proc();
diff --git a/test/Preprocessor/_Pragma-dependency.c b/test/Preprocessor/_Pragma-dependency.c
index da1d87f741e6..17c5355302c2 100644
--- a/test/Preprocessor/_Pragma-dependency.c
+++ b/test/Preprocessor/_Pragma-dependency.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -E 2>&1 | grep 'DO_PRAGMA (STR' &&
+// RUN: clang-cc %s -E 2>&1 | grep 'DO_PRAGMA (STR'
// RUN: clang-cc %s -E 2>&1 | grep '7:3'
#define DO_PRAGMA _Pragma
diff --git a/test/Preprocessor/_Pragma-physloc.c b/test/Preprocessor/_Pragma-physloc.c
index 87379491676d..016c97b82fd8 100644
--- a/test/Preprocessor/_Pragma-physloc.c
+++ b/test/Preprocessor/_Pragma-physloc.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -E | grep '#pragma x y z' &&
+// RUN: clang-cc %s -E | grep '#pragma x y z'
// RUN: clang-cc %s -E | grep '#pragma a b c'
_Pragma("x y z")
diff --git a/test/Preprocessor/assembler-with-cpp.c b/test/Preprocessor/assembler-with-cpp.c
index 4f1c443fc042..693d5b81a17f 100644
--- a/test/Preprocessor/assembler-with-cpp.c
+++ b/test/Preprocessor/assembler-with-cpp.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=0 -E %s -o - | FileCheck -strict-whitespace -check-prefix=CHECK-Identifiers-False %s &&
+// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=0 -E %s -o - | FileCheck -strict-whitespace -check-prefix=CHECK-Identifiers-False %s
#ifndef __ASSEMBLER__
#error "__ASSEMBLER__ not defined"
@@ -49,7 +49,7 @@
6: FOO(blarg)
// CHECK-Identifiers-False: 6: blarg $foo
-// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=1 -E %s -o - | FileCheck -check-prefix=CHECK-Identifiers-True -strict-whitespace %s &&
+// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=1 -E %s -o - | FileCheck -check-prefix=CHECK-Identifiers-True -strict-whitespace %s
#define FOO(name) name ## $foo
7: FOO(blarg)
// CHECK-Identifiers-True: 7: blarg$foo
@@ -72,4 +72,3 @@
11: T11(b)
// CHECK-Identifiers-True: 11: #0
-// RUN: true
diff --git a/test/Preprocessor/builtin_line.c b/test/Preprocessor/builtin_line.c
index db01e47995a8..06a2ac20d04c 100644
--- a/test/Preprocessor/builtin_line.c
+++ b/test/Preprocessor/builtin_line.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -E | grep "^ 4" &&
+// RUN: clang-cc %s -E | grep "^ 4"
#define FOO __LINE__
FOO
diff --git a/test/Preprocessor/comment_save_macro.c b/test/Preprocessor/comment_save_macro.c
index b9a25ed2e7f3..76a21bfbdea8 100644
--- a/test/Preprocessor/comment_save_macro.c
+++ b/test/Preprocessor/comment_save_macro.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -E -C %s | FileCheck -check-prefix=CHECK-C -strict-whitespace %s &&
+// RUN: clang-cc -E -C %s | FileCheck -check-prefix=CHECK-C -strict-whitespace %s
// CHECK-C: boo bork bar // zot
-// RUN: clang-cc -E -CC %s | FileCheck -check-prefix=CHECK-CC -strict-whitespace %s &&
+// RUN: clang-cc -E -CC %s | FileCheck -check-prefix=CHECK-CC -strict-whitespace %s
// CHECK-CC: boo bork /* blah*/ bar // zot
// RUN: clang-cc -E %s | FileCheck -check-prefix=CHECK -strict-whitespace %s
diff --git a/test/Preprocessor/cxx_and.cpp b/test/Preprocessor/cxx_and.cpp
index 971b7bc991dc..747091387fde 100644
--- a/test/Preprocessor/cxx_and.cpp
+++ b/test/Preprocessor/cxx_and.cpp
@@ -1,6 +1,6 @@
-// RUN: clang-cc -DA -DB -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA -E %s | grep 'int a = 927 == 927' &&
-// RUN: clang-cc -DB -E %s | grep 'int a = 927 == 927' &&
+// RUN: clang-cc -DA -DB -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA -E %s | grep 'int a = 927 == 927'
+// RUN: clang-cc -DB -E %s | grep 'int a = 927 == 927'
// RUN: clang-cc -E %s | grep 'int a = 927 == 927'
#if defined(A) and defined(B)
#define X 37
diff --git a/test/Preprocessor/cxx_bitand.cpp b/test/Preprocessor/cxx_bitand.cpp
index 8d7fe678e3e0..e6b7c2c6370a 100644
--- a/test/Preprocessor/cxx_bitand.cpp
+++ b/test/Preprocessor/cxx_bitand.cpp
@@ -1,5 +1,5 @@
-// RUN: clang-cc -DA=1 -DB=2 -E %s | grep 'int a = 927 == 927' &&
-// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 37 == 37' &&
+// RUN: clang-cc -DA=1 -DB=2 -E %s | grep 'int a = 927 == 927'
+// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 37 == 37'
// RUN: clang-cc -E %s | grep 'int a = 927 == 927'
#if A bitand B
#define X 37
diff --git a/test/Preprocessor/cxx_bitor.cpp b/test/Preprocessor/cxx_bitor.cpp
index 7645c7ee5133..e72fcb44a950 100644
--- a/test/Preprocessor/cxx_bitor.cpp
+++ b/test/Preprocessor/cxx_bitor.cpp
@@ -1,7 +1,7 @@
-// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA=0 -DB=1 -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA=1 -DB=0 -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA=0 -DB=0 -E %s | grep 'int a = 927 == 927' &&
+// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA=0 -DB=1 -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA=1 -DB=0 -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA=0 -DB=0 -E %s | grep 'int a = 927 == 927'
// RUN: clang-cc -E %s | grep 'int a = 927 == 927'
#if A bitor B
#define X 37
diff --git a/test/Preprocessor/cxx_compl.cpp b/test/Preprocessor/cxx_compl.cpp
index f1cc6d2800d5..b319c51f29fb 100644
--- a/test/Preprocessor/cxx_compl.cpp
+++ b/test/Preprocessor/cxx_compl.cpp
@@ -1,5 +1,5 @@
-// RUN: clang-cc -DA=1 -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA=0 -E %s | grep 'int a = 927 == 927' &&
+// RUN: clang-cc -DA=1 -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA=0 -E %s | grep 'int a = 927 == 927'
// RUN: clang-cc -E %s | grep 'int a = 927 == 927'
#if compl 0 bitand A
#define X 37
diff --git a/test/Preprocessor/cxx_not.cpp b/test/Preprocessor/cxx_not.cpp
index dd3190117d92..2272941b68da 100644
--- a/test/Preprocessor/cxx_not.cpp
+++ b/test/Preprocessor/cxx_not.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -DA=1 -E %s | grep 'int a = 927 == 927' &&
+// RUN: clang-cc -DA=1 -E %s | grep 'int a = 927 == 927'
// RUN: clang-cc -E %s | grep 'int a = 37 == 37'
#if not defined(A)
#define X 37
diff --git a/test/Preprocessor/cxx_not_eq.cpp b/test/Preprocessor/cxx_not_eq.cpp
index 4940f3b0a7bf..92418b287a50 100644
--- a/test/Preprocessor/cxx_not_eq.cpp
+++ b/test/Preprocessor/cxx_not_eq.cpp
@@ -1,5 +1,5 @@
-// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 927 == 927' &&
-// RUN: clang-cc -E %s | grep 'int a = 927 == 927' &&
+// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 927 == 927'
+// RUN: clang-cc -E %s | grep 'int a = 927 == 927'
// RUN: clang-cc -DA=1 -DB=2 -E %s | grep 'int a = 37 == 37'
#if A not_eq B
#define X 37
diff --git a/test/Preprocessor/cxx_oper_keyword.cpp b/test/Preprocessor/cxx_oper_keyword.cpp
index faae68741eed..0464e97eb903 100644
--- a/test/Preprocessor/cxx_oper_keyword.cpp
+++ b/test/Preprocessor/cxx_oper_keyword.cpp
@@ -1,4 +1,4 @@
-// RUN: not clang-cc %s -E &&
+// RUN: not clang-cc %s -E
// RUN: clang-cc %s -E -fno-operator-names
// Not valid in C++ unless -fno-operator-names is passed.
diff --git a/test/Preprocessor/cxx_or.cpp b/test/Preprocessor/cxx_or.cpp
index 133f28516b42..2f7c0a5d65db 100644
--- a/test/Preprocessor/cxx_or.cpp
+++ b/test/Preprocessor/cxx_or.cpp
@@ -1,6 +1,6 @@
-// RUN: clang-cc -DA -DB -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DB -E %s | grep 'int a = 37 == 37' &&
+// RUN: clang-cc -DA -DB -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DB -E %s | grep 'int a = 37 == 37'
// RUN: clang-cc -E %s | grep 'int a = 927 == 927'
#if defined(A) or defined(B)
#define X 37
diff --git a/test/Preprocessor/cxx_true.cpp b/test/Preprocessor/cxx_true.cpp
index e35c54d7b3fc..80aa04e2b99e 100644
--- a/test/Preprocessor/cxx_true.cpp
+++ b/test/Preprocessor/cxx_true.cpp
@@ -1,5 +1,5 @@
-/* RUN: clang-cc -E %s -x=c++ | grep block_1 &&
- RUN: clang-cc -E %s -x=c++ | not grep block_2 &&
+/* RUN: clang-cc -E %s -x=c++ | grep block_1
+ RUN: clang-cc -E %s -x=c++ | not grep block_2
RUN: clang-cc -E %s -x=c | not grep block
*/
diff --git a/test/Preprocessor/cxx_xor.cpp b/test/Preprocessor/cxx_xor.cpp
index a38c3c5454b9..e6df9bb819e1 100644
--- a/test/Preprocessor/cxx_xor.cpp
+++ b/test/Preprocessor/cxx_xor.cpp
@@ -1,7 +1,7 @@
-// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 927 == 927' &&
-// RUN: clang-cc -DA=0 -DB=1 -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA=1 -DB=0 -E %s | grep 'int a = 37 == 37' &&
-// RUN: clang-cc -DA=0 -DB=0 -E %s | grep 'int a = 927 == 927' &&
+// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 927 == 927'
+// RUN: clang-cc -DA=0 -DB=1 -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA=1 -DB=0 -E %s | grep 'int a = 37 == 37'
+// RUN: clang-cc -DA=0 -DB=0 -E %s | grep 'int a = 927 == 927'
// RUN: clang-cc -E %s | grep 'int a = 927 == 927'
#if A xor B
#define X 37
diff --git a/test/Preprocessor/dependencies-and-pp.c b/test/Preprocessor/dependencies-and-pp.c
index 1dc4d026b18d..5359d0af4d7a 100644
--- a/test/Preprocessor/dependencies-and-pp.c
+++ b/test/Preprocessor/dependencies-and-pp.c
@@ -1,5 +1,5 @@
-// RUN: clang -E -o %t.1 %s &&
-// RUN: clang -E -MD -MF %t.d -MT foo -o %t.2 %s &&
-// RUN: diff %t.1 %t.2 &&
-// RUN: grep "foo:" %t.d &&
+// RUN: clang -E -o %t.1 %s
+// RUN: clang -E -MD -MF %t.d -MT foo -o %t.2 %s
+// RUN: diff %t.1 %t.2
+// RUN: grep "foo:" %t.d
// RUN: grep "dependencies-and-pp.c" %t.d
diff --git a/test/Preprocessor/dump-options.c b/test/Preprocessor/dump-options.c
index 6910e1a314e4..8302f1a32615 100644
--- a/test/Preprocessor/dump-options.c
+++ b/test/Preprocessor/dump-options.c
@@ -1,3 +1,3 @@
-// RUN: clang %s -E -dD | grep __INTMAX_MAX__ &&
+// RUN: clang %s -E -dD | grep __INTMAX_MAX__
// RUN: clang %s -E -dM | grep __INTMAX_MAX__
diff --git a/test/Preprocessor/dump_macros.c b/test/Preprocessor/dump_macros.c
index d3e06b2bfac7..bdc69536778d 100644
--- a/test/Preprocessor/dump_macros.c
+++ b/test/Preprocessor/dump_macros.c
@@ -1,29 +1,29 @@
-// RUN: clang-cc -E -dM %s -o %t &&
+// RUN: clang-cc -E -dM %s -o %t
// Space even without expansion tokens
-// RUN: grep "#define A(x) " %t &&
+// RUN: grep "#define A(x) " %t
#define A(x)
// Space before expansion list.
-// RUN: grep "#define B(x,y) x y" %t &&
+// RUN: grep "#define B(x,y) x y" %t
#define B(x,y)x y
// No space in expansion list.
-// RUN: grep "#define C(x,y) x y" %t &&
+// RUN: grep "#define C(x,y) x y" %t
#define C(x, y) x y
// No paste avoidance.
-// RUN: grep "#define X() .." %t &&
+// RUN: grep "#define X() .." %t
#define X() ..
// Simple test.
-// RUN: grep "#define Y ." %t &&
-// RUN: grep "#define Z X()Y" %t &&
+// RUN: grep "#define Y ." %t
+// RUN: grep "#define Z X()Y" %t
#define Y .
#define Z X()Y
// gcc prints macros at end of translation unit, so last one wins.
-// RUN: grep "#define foo 2" %t &&
+// RUN: grep "#define foo 2" %t
// RUN: not grep "#define foo 1" %t
#define foo 1
#undef foo
diff --git a/test/Preprocessor/expr_comma.c b/test/Preprocessor/expr_comma.c
index 0a24baca46c9..88ceabf8e480 100644
--- a/test/Preprocessor/expr_comma.c
+++ b/test/Preprocessor/expr_comma.c
@@ -1,5 +1,5 @@
// Comma is not allowed in C89
-// RUN: not clang-cc -E %s -std=c89 -pedantic-errors &&
+// RUN: not clang-cc -E %s -std=c89 -pedantic-errors
// Comma is allowed if unevaluated in C99
// RUN: clang-cc -E %s -std=c99 -pedantic-errors
diff --git a/test/Preprocessor/expr_invalid_tok.c b/test/Preprocessor/expr_invalid_tok.c
index 5e750a462be0..8bc2b8eb75c9 100644
--- a/test/Preprocessor/expr_invalid_tok.c
+++ b/test/Preprocessor/expr_invalid_tok.c
@@ -1,5 +1,5 @@
-// RUN: not clang-cc -E %s 2>&1 | grep 'invalid token at start of a preprocessor expression' &&
-// RUN: not clang-cc -E %s 2>&1 | grep 'token is not a valid binary operator in a preprocessor subexpression' &&
+// RUN: not clang-cc -E %s 2>&1 | grep 'invalid token at start of a preprocessor expression'
+// RUN: not clang-cc -E %s 2>&1 | grep 'token is not a valid binary operator in a preprocessor subexpression'
// RUN: not clang-cc -E %s 2>&1 | grep ':14: error: expected end of line in preprocessor expression'
// PR2220
diff --git a/test/Preprocessor/expr_liveness.c b/test/Preprocessor/expr_liveness.c
index 3d1e25edd4e6..d44b196afa83 100644
--- a/test/Preprocessor/expr_liveness.c
+++ b/test/Preprocessor/expr_liveness.c
@@ -1,4 +1,4 @@
-/* RUN: clang-cc -E %s -DNO_ERRORS -Werror -Wundef &&
+/* RUN: clang-cc -E %s -DNO_ERRORS -Werror -Wundef
RUN: not clang-cc -E %s
*/
diff --git a/test/Preprocessor/feature_tests.c b/test/Preprocessor/feature_tests.c
index 9a29ab96c93e..dbfde4b430b7 100644
--- a/test/Preprocessor/feature_tests.c
+++ b/test/Preprocessor/feature_tests.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s --triple=i686-apple-darwin9 &&
+// RUN: clang-cc %s --triple=i686-apple-darwin9
// RUN: clang-cc %s -E --triple=i686-apple-darwin9
#ifndef __has_feature
#error Should have __has_feature
diff --git a/test/Preprocessor/hash_line.c b/test/Preprocessor/hash_line.c
index 7ed65d1b424d..31f708ce73ad 100644
--- a/test/Preprocessor/hash_line.c
+++ b/test/Preprocessor/hash_line.c
@@ -1,6 +1,6 @@
// The 1 and # should not go on the same line.
-// RUN: clang-cc %s -E | not grep "1 #" &&
-// RUN: clang-cc %s -E | grep '^1$' &&
+// RUN: clang-cc %s -E | not grep "1 #"
+// RUN: clang-cc %s -E | grep '^1$'
// RUN: clang-cc %s -E | grep '^ #$'
1
#define EMPTY
diff --git a/test/Preprocessor/header_lookup1.c b/test/Preprocessor/header_lookup1.c
index df58a6ea9c54..10049adcd374 100644
--- a/test/Preprocessor/header_lookup1.c
+++ b/test/Preprocessor/header_lookup1.c
@@ -1,2 +1,2 @@
-// RUN: clang-cc -I /usr/include %s -E | grep 'stdio.h.*3.*4'
+// RUN: clang -I /usr/include %s -E | grep 'stdio.h.*3.*4'
#include <stdio.h>
diff --git a/test/Preprocessor/if_warning.c b/test/Preprocessor/if_warning.c
index 5567513c3630..2ce7b3159982 100644
--- a/test/Preprocessor/if_warning.c
+++ b/test/Preprocessor/if_warning.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -Eonly -Werror=undef -verify &&
+// RUN: clang-cc %s -Eonly -Werror=undef -verify
// RUN: clang-cc %s -Eonly -Werror-undef -verify
extern int x;
diff --git a/test/Preprocessor/include-pth.c b/test/Preprocessor/include-pth.c
index 2afc66a55b0b..5634d719f567 100644
--- a/test/Preprocessor/include-pth.c
+++ b/test/Preprocessor/include-pth.c
@@ -1,3 +1,3 @@
-// RUN: clang-cc -emit-pth %s -o %t &&
+// RUN: clang-cc -emit-pth %s -o %t
// RUN: clang-cc -include-pth %t %s -E | grep 'file_to_include' | count 2
#include "file_to_include.h"
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index 800b7506f4c2..2926900e78c5 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -1,15 +1,15 @@
-// RUN: clang-cc -E -dM -x=assembler-with-cpp < /dev/null | FileCheck -check-prefix ASM %s &&
+// RUN: clang-cc -E -dM -x=assembler-with-cpp < /dev/null | FileCheck -check-prefix ASM %s
//
// ASM:#define __ASSEMBLER__ 1
//
//
-// RUN: clang-cc -fblocks -E -dM < /dev/null | FileCheck -check-prefix BLOCKS %s &&
+// RUN: clang-cc -fblocks -E -dM < /dev/null | FileCheck -check-prefix BLOCKS %s
//
// BLOCKS:#define __BLOCKS__ 1
// BLOCKS:#define __block __attribute__((__blocks__(byref)))
//
//
-// RUN: clang-cc -x=c++ -std=c++0x -E -dM < /dev/null | FileCheck -check-prefix CXX0X %s &&
+// RUN: clang-cc -x=c++ -std=c++0x -E -dM < /dev/null | FileCheck -check-prefix CXX0X %s
//
// CXX0X:#define _GNU_SOURCE 1
// CXX0X:#define __DEPRECATED 1
@@ -20,7 +20,7 @@
// CXX0X:#define __private_extern__ extern
//
//
-// RUN: clang-cc -x=c++ -std=c++98 -E -dM < /dev/null | FileCheck -check-prefix CXX98 %s &&
+// RUN: clang-cc -x=c++ -std=c++98 -E -dM < /dev/null | FileCheck -check-prefix CXX98 %s
//
// CXX98:#define _GNU_SOURCE 1
// CXX98:#define __DEPRECATED 1
@@ -30,13 +30,13 @@
// CXX98:#define __private_extern__ extern
//
//
-// RUN: clang-cc -std=c99 -E -dM < /dev/null | FileCheck -check-prefix C99 %s &&
+// RUN: clang-cc -std=c99 -E -dM < /dev/null | FileCheck -check-prefix C99 %s
//
// C99:#define __STDC_VERSION__ 199901L
// C99:#define __STRICT_ANSI__ 1
//
//
-// RUN: clang-cc -E -dM -fms-extensions=0 < /dev/null | FileCheck -check-prefix COMMON %s &&
+// RUN: clang-cc -E -dM -fms-extensions=0 < /dev/null | FileCheck -check-prefix COMMON %s
//
// COMMON:#define __CONSTANT_CFSTRINGS__ 1
// COMMON:#define __FINITE_MATH_ONLY__ 0
@@ -53,10 +53,10 @@
// COMMON:#define __llvm__ 1
//
//
-// RUN: clang-cc -ffreestanding -E -dM < /dev/null | FileCheck -check-prefix FREESTANDING %s &&
+// RUN: clang-cc -ffreestanding -E -dM < /dev/null | FileCheck -check-prefix FREESTANDING %s
// FREESTANDING:#define __STDC_HOSTED__ 0
//
-// RUN: clang-cc -x=c++ -std=gnu++98 -E -dM < /dev/null | FileCheck -check-prefix GXX98 %s &&
+// RUN: clang-cc -x=c++ -std=gnu++98 -E -dM < /dev/null | FileCheck -check-prefix GXX98 %s
//
// GXX98:#define _GNU_SOURCE 1
// GXX98:#define __DEPRECATED 1
@@ -66,12 +66,12 @@
// GXX98:#define __private_extern__ extern
//
//
-// RUN: clang-cc -std=iso9899:199409 -E -dM < /dev/null | FileCheck -check-prefix C94 %s &&
+// RUN: clang-cc -std=iso9899:199409 -E -dM < /dev/null | FileCheck -check-prefix C94 %s
//
// C94:#define __STDC_VERSION__ 199409L
//
//
-// RUN: clang-cc -fms-extensions -E -dM < /dev/null | FileCheck -check-prefix MSEXT %s &&
+// RUN: clang-cc -fms-extensions -E -dM < /dev/null | FileCheck -check-prefix MSEXT %s
//
// MSEXT-NOT:#define __STDC__
// MSEXT:#define __int16 __INT16_TYPE__
@@ -80,45 +80,41 @@
// MSEXT:#define __int8 __INT8_TYPE__
//
//
-// RUN: clang-cc -x=objective-c -E -dM < /dev/null | FileCheck -check-prefix OBJC %s &&
+// RUN: clang-cc -x=objective-c -E -dM < /dev/null | FileCheck -check-prefix OBJC %s
//
// OBJC:#define OBJC_NEW_PROPERTIES 1
+// OBJC:#define __NEXT_RUNTIME__ 1
// OBJC:#define __OBJC__ 1
//
-//
-// RUN: clang-cc -x=objective-c -fobjc-gc -E -dM < /dev/null | FileCheck -check-prefix OBJCGC %s &&
//
-// OBJCGC:#define __OBJC_GC__ 1
+// RUN: clang-cc -x=objective-c -fobjc-gc -E -dM < /dev/null | FileCheck -check-prefix OBJCGC %s
//
-//
-// RUN: clang-cc -x=objective-c -fnext-runtime -E -dM < /dev/null | FileCheck -check-prefix NEXTRT %s &&
-//
-// NEXTRT:#define __NEXT_RUNTIME__ 1
+// OBJCGC:#define __OBJC_GC__ 1
//
//
-// RUN: clang-cc -x=objective-c -fobjc-nonfragile-abi -E -dM < /dev/null | FileCheck -check-prefix NONFRAGILE %s &&
+// RUN: clang-cc -x=objective-c -fobjc-nonfragile-abi -E -dM < /dev/null | FileCheck -check-prefix NONFRAGILE %s
//
// NONFRAGILE:#define OBJC_ZEROCOST_EXCEPTIONS 1
// NONFRAGILE:#define __OBJC2__ 1
//
//
-// RUN: clang-cc -O1 -E -dM < /dev/null | FileCheck -check-prefix O1 %s &&
+// RUN: clang-cc -O1 -E -dM < /dev/null | FileCheck -check-prefix O1 %s
//
// O1:#define __OPTIMIZE__ 1
//
//
-// RUN: clang-cc -fpascal-strings -E -dM < /dev/null | FileCheck -check-prefix PASCAL %s &&
+// RUN: clang-cc -fpascal-strings -E -dM < /dev/null | FileCheck -check-prefix PASCAL %s
//
// PASCAL:#define __PASCAL_STRINGS__ 1
//
//
-// RUN: clang-cc -fsigned-char -E -dM -fms-extensions=0 < /dev/null | FileCheck -check-prefix SCHAR %s &&
+// RUN: clang-cc -fsigned-char -E -dM -fms-extensions=0 < /dev/null | FileCheck -check-prefix SCHAR %s
//
// SCHAR:#define __STDC__ 1
// SCHAR-NOT:#define __UNSIGNED_CHAR__
// SCHAR:#define __clang__ 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -check-prefix ARM %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -check-prefix ARM %s
//
// ARM:#define __APCS_32__ 1
// ARM:#define __ARMEL__ 1
@@ -155,6 +151,7 @@
// ARM:#define __FLT_RADIX__ 2
// ARM:#define __INT16_TYPE__ short
// ARM:#define __INT32_TYPE__ int
+// ARM:#define __INT64_C_SUFFIX__ LL
// ARM:#define __INT64_TYPE__ long long int
// ARM:#define __INT8_TYPE__ char
// ARM:#define __INTMAX_MAX__ 9223372036854775807LL
@@ -193,7 +190,7 @@
// ARM:#define __arm 1
// ARM:#define __arm__ 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=bfin-none-none < /dev/null | FileCheck -check-prefix BFIN %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=bfin-none-none < /dev/null | FileCheck -check-prefix BFIN %s
//
// BFIN:#define BFIN 1
// BFIN:#define __ADSPBLACKFIN__ 1
@@ -232,6 +229,7 @@
// BFIN:#define __FLT_RADIX__ 2
// BFIN:#define __INT16_TYPE__ short
// BFIN:#define __INT32_TYPE__ int
+// BFIN:#define __INT64_C_SUFFIX__ LL
// BFIN:#define __INT64_TYPE__ long long int
// BFIN:#define __INT8_TYPE__ char
// BFIN:#define __INTMAX_MAX__ 9223372036854775807LL
@@ -268,7 +266,7 @@
// BFIN:#define __bfin__ 1
// BFIN:#define bfin 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=i386-none-none < /dev/null | FileCheck -check-prefix I386 %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=i386-none-none < /dev/null | FileCheck -check-prefix I386 %s
//
// I386:#define __CHAR_BIT__ 8
// I386:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
@@ -302,6 +300,7 @@
// I386:#define __FLT_RADIX__ 2
// I386:#define __INT16_TYPE__ short
// I386:#define __INT32_TYPE__ int
+// I386:#define __INT64_C_SUFFIX__ LL
// I386:#define __INT64_TYPE__ long long int
// I386:#define __INT8_TYPE__ char
// I386:#define __INTMAX_MAX__ 9223372036854775807LL
@@ -344,7 +343,7 @@
// I386:#define __tune_nocona__ 1
// I386:#define i386 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=msp430-none-none < /dev/null | FileCheck -check-prefix MSP430 %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=msp430-none-none < /dev/null | FileCheck -check-prefix MSP430 %s
//
// MSP430:#define MSP430 1
// MSP430:#define __CHAR_BIT__ 8
@@ -378,7 +377,8 @@
// MSP430:#define __FLT_MIN__ 1.17549435e-38F
// MSP430:#define __FLT_RADIX__ 2
// MSP430:#define __INT16_TYPE__ short
-// MSP430:#define __INT32_TYPE__ long long
+// MSP430:#define __INT32_C_SUFFIX__ L
+// MSP430:#define __INT32_TYPE__ long int
// MSP430:#define __INT8_TYPE__ char
// MSP430:#define __INTMAX_MAX__ 2147483647L
// MSP430:#define __INTMAX_TYPE__ long int
@@ -408,12 +408,12 @@
// MSP430:#define __SIZE_TYPE__ unsigned int
// MSP430:#define __UINTMAX_TYPE__ long unsigned int
// MSP430:#define __USER_LABEL_PREFIX__ _
-// MSP430:#define __WCHAR_MAX__ 2147483647
+// MSP430:#define __WCHAR_MAX__ 32767
// MSP430:#define __WCHAR_TYPE__ int
// MSP430:#define __WINT_TYPE__ int
// MSP430:#define __clang__ 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=pic16-none-none < /dev/null | FileCheck -check-prefix PIC16 %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=pic16-none-none < /dev/null | FileCheck -check-prefix PIC16 %s
//
// PIC16:#define _CONFIG(conf) asm("CONFIG "#conf)
// PIC16:#define __CHAR_BIT__ 8
@@ -447,7 +447,8 @@
// PIC16:#define __FLT_MIN__ 1.17549435e-38F
// PIC16:#define __FLT_RADIX__ 2
// PIC16:#define __INT16_TYPE__ short
-// PIC16:#define __INT32_TYPE__ long long
+// PIC16:#define __INT32_C_SUFFIX__ L
+// PIC16:#define __INT32_TYPE__ long int
// PIC16:#define __INT8_TYPE__ char
// PIC16:#define __INTMAX_MAX__ 2147483647L
// PIC16:#define __INTMAX_TYPE__ long int
@@ -476,7 +477,7 @@
// PIC16:#define __SIZE_TYPE__ unsigned int
// PIC16:#define __UINTMAX_TYPE__ long unsigned int
// PIC16:#define __USER_LABEL_PREFIX__ _
-// PIC16:#define __WCHAR_MAX__ 2147483647
+// PIC16:#define __WCHAR_MAX__ 32767
// PIC16:#define __WCHAR_TYPE__ int
// PIC16:#define __WINT_TYPE__ int
// PIC16:#define __clang__ 1
@@ -488,7 +489,7 @@
// PIC16:#define ram __attribute__((address_space(0)))
// PIC16:#define rom __attribute__((address_space(1)))
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=powerpc64-none-none < /dev/null | FileCheck -check-prefix PPC64 %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=powerpc64-none-none -fsigned-char=0 < /dev/null | FileCheck -check-prefix PPC64 %s
//
// PPC64:#define _ARCH_PPC 1
// PPC64:#define _ARCH_PPC64 1
@@ -528,6 +529,7 @@
// PPC64:#define __FLT_RADIX__ 2
// PPC64:#define __INT16_TYPE__ short
// PPC64:#define __INT32_TYPE__ int
+// PPC64:#define __INT64_C_SUFFIX__ L
// PPC64:#define __INT64_TYPE__ long int
// PPC64:#define __INT8_TYPE__ char
// PPC64:#define __INTMAX_MAX__ 9223372036854775807L
@@ -568,7 +570,7 @@
// PPC64:#define __ppc64__ 1
// PPC64:#define __ppc__ 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=powerpc-none-none < /dev/null | FileCheck -check-prefix PPC %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=powerpc-none-none -fsigned-char=0 < /dev/null | FileCheck -check-prefix PPC %s
//
// PPC:#define _ARCH_PPC 1
// PPC:#define _BIG_ENDIAN 1
@@ -606,6 +608,7 @@
// PPC:#define __FLT_RADIX__ 2
// PPC:#define __INT16_TYPE__ short
// PPC:#define __INT32_TYPE__ int
+// PPC:#define __INT64_C_SUFFIX__ LL
// PPC:#define __INT64_TYPE__ long long int
// PPC:#define __INT8_TYPE__ char
// PPC:#define __INTMAX_MAX__ 9223372036854775807LL
@@ -644,7 +647,7 @@
// PPC:#define __WINT_TYPE__ int
// PPC:#define __ppc__ 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=s390x-none-none < /dev/null | FileCheck -check-prefix S390X %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=s390x-none-none -fsigned-char=0 < /dev/null | FileCheck -check-prefix S390X %s
//
// S390X:#define __CHAR_BIT__ 8
// S390X:#define __CHAR_UNSIGNED__ 1
@@ -679,7 +682,8 @@
// S390X:#define __FLT_RADIX__ 2
// S390X:#define __INT16_TYPE__ short
// S390X:#define __INT32_TYPE__ int
-// S390X:#define __INT64_TYPE__ long long int
+// S390X:#define __INT64_C_SUFFIX__ L
+// S390X:#define __INT64_TYPE__ long int
// S390X:#define __INT8_TYPE__ char
// S390X:#define __INTMAX_MAX__ 9223372036854775807LL
// S390X:#define __INTMAX_TYPE__ long long int
@@ -714,7 +718,7 @@
// S390X:#define __s390__ 1
// S390X:#define __s390x__ 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=sparc-none-none < /dev/null | FileCheck -check-prefix SPARC %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=sparc-none-none < /dev/null | FileCheck -check-prefix SPARC %s
//
// SPARC:#define __CHAR_BIT__ 8
// SPARC:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
@@ -748,6 +752,7 @@
// SPARC:#define __FLT_RADIX__ 2
// SPARC:#define __INT16_TYPE__ short
// SPARC:#define __INT32_TYPE__ int
+// SPARC:#define __INT64_C_SUFFIX__ LL
// SPARC:#define __INT64_TYPE__ long long int
// SPARC:#define __INT8_TYPE__ char
// SPARC:#define __INTMAX_MAX__ 9223372036854775807LL
@@ -787,7 +792,7 @@
// SPARC:#define __sparcv8 1
// SPARC:#define sparc 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=tce-none-none < /dev/null | FileCheck -check-prefix TCE %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=tce-none-none < /dev/null | FileCheck -check-prefix TCE %s
//
// TCE:#define __CHAR_BIT__ 8
// TCE:#define __DBL_DENORM_MIN__ 1.40129846e-45F
@@ -858,7 +863,7 @@
// TCE:#define __tce__ 1
// TCE:#define tce 1
//
-// RUN: clang-cc -E -dM -ffreestanding -triple=x86_64-none-none < /dev/null | FileCheck -check-prefix X86_64 %s &&
+// RUN: clang-cc -E -dM -ffreestanding -triple=x86_64-none-none < /dev/null | FileCheck -check-prefix X86_64 %s
//
// X86_64:#define _LP64 1
// X86_64:#define __CHAR_BIT__ 8
@@ -893,6 +898,7 @@
// X86_64:#define __FLT_RADIX__ 2
// X86_64:#define __INT16_TYPE__ short
// X86_64:#define __INT32_TYPE__ int
+// X86_64:#define __INT64_C_SUFFIX__ L
// X86_64:#define __INT64_TYPE__ long int
// X86_64:#define __INT8_TYPE__ char
// X86_64:#define __INTMAX_MAX__ 9223372036854775807L
@@ -942,4 +948,3 @@
// X86_64:#define __x86_64 1
// X86_64:#define __x86_64__ 1
//
-// RUN: true
diff --git a/test/Preprocessor/line-directive.c b/test/Preprocessor/line-directive.c
index 4ebf95bab44c..b79b1d98ea02 100644
--- a/test/Preprocessor/line-directive.c
+++ b/test/Preprocessor/line-directive.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -fsyntax-only -verify -pedantic -fms-extensions=0 %s &&
-// RUN: clang-cc -E %s 2>&1 | grep 'blonk.c:92:2: error: #error ABC' &&
+// RUN: clang-cc -fsyntax-only -verify -pedantic -fms-extensions=0 %s
+// RUN: clang-cc -E %s 2>&1 | grep 'blonk.c:92:2: error: #error ABC'
// RUN: clang-cc -E %s 2>&1 | grep 'blonk.c:93:2: error: #error DEF'
#line 'a' // expected-error {{#line directive requires a positive integer argument}}
diff --git a/test/Preprocessor/macro-multiline.c b/test/Preprocessor/macro-multiline.c
index ba988253b272..9f24ae8e5563 100644
--- a/test/Preprocessor/macro-multiline.c
+++ b/test/Preprocessor/macro-multiline.c
@@ -1,6 +1,6 @@
-// RUN: clang -E %s "-DX=A &&
-// RUN: THIS_SHOULD_NOT_EXIST_IN_THE_OUTPUT" > %t &&
-// RUN: grep "GOOD: A" %t &&
+// RUN: clang -E %s "-DX=A
+// RUN: THIS_SHOULD_NOT_EXIST_IN_THE_OUTPUT" > %t
+// RUN: grep "GOOD: A" %t
// RUN: not grep THIS_SHOULD_NOT_EXIST_IN_THE_OUTPUT %t
// rdar://6762183
diff --git a/test/Preprocessor/macro_disable.c b/test/Preprocessor/macro_disable.c
index ff861d262197..f102ddddafc7 100644
--- a/test/Preprocessor/macro_disable.c
+++ b/test/Preprocessor/macro_disable.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -E %s | grep 'a: 2 + M_0(3)(4)(5);' &&
+// RUN: clang-cc -E %s | grep 'a: 2 + M_0(3)(4)(5);'
// RUN: clang-cc -E %s | grep 'b: 4 + 4 + 3 + 2 + 1 + M_0(3)(2)(1);'
#define M_0(x) M_ ## x
diff --git a/test/Preprocessor/macro_expand.c b/test/Preprocessor/macro_expand.c
index 74b3922d1e13..a93c04e373c6 100644
--- a/test/Preprocessor/macro_expand.c
+++ b/test/Preprocessor/macro_expand.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -E %s | grep '^A: Y$' &&
-// RUN: clang-cc -E %s | grep '^B: f()$' &&
+// RUN: clang-cc -E %s | grep '^A: Y$'
+// RUN: clang-cc -E %s | grep '^B: f()$'
// RUN: clang-cc -E %s | grep '^C: for()$'
#define X() Y
diff --git a/test/Preprocessor/macro_fn_comma_swallow.c b/test/Preprocessor/macro_fn_comma_swallow.c
index d39d4e7841d5..c98e37823453 100644
--- a/test/Preprocessor/macro_fn_comma_swallow.c
+++ b/test/Preprocessor/macro_fn_comma_swallow.c
@@ -1,7 +1,7 @@
// Test the GNU comma swallowing extension.
-// RUN: clang-cc %s -E | grep 'foo{A, }' &&
-// RUN: clang-cc %s -E | grep 'fo2{A,}' &&
-// RUN: clang-cc %s -E | grep '{foo}' &&
+// RUN: clang-cc %s -E | grep 'foo{A, }'
+// RUN: clang-cc %s -E | grep 'fo2{A,}'
+// RUN: clang-cc %s -E | grep '{foo}'
#define X(Y) foo{A, Y}
X()
diff --git a/test/Preprocessor/macro_fn_disable_expand.c b/test/Preprocessor/macro_fn_disable_expand.c
index d99c01832eac..c3b067dfc965 100644
--- a/test/Preprocessor/macro_fn_disable_expand.c
+++ b/test/Preprocessor/macro_fn_disable_expand.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -E | grep 'bar foo (2)' &&
+// RUN: clang-cc %s -E | grep 'bar foo (2)'
// RUN: clang-cc %s -E | grep 'm(ABCD)'
#define foo(x) bar x
diff --git a/test/Preprocessor/macro_fn_lparen_scan.c b/test/Preprocessor/macro_fn_lparen_scan.c
index 1056fd82341a..77e1fb9a3d4b 100644
--- a/test/Preprocessor/macro_fn_lparen_scan.c
+++ b/test/Preprocessor/macro_fn_lparen_scan.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -E %s | grep 'noexp: foo y' &&
-// RUN: clang-cc -E %s | grep 'expand: abc' &&
-// RUN: clang-cc -E %s | grep 'noexp2: foo nonexp' &&
+// RUN: clang-cc -E %s | grep 'noexp: foo y'
+// RUN: clang-cc -E %s | grep 'expand: abc'
+// RUN: clang-cc -E %s | grep 'noexp2: foo nonexp'
// RUN: clang-cc -E %s | grep 'expand2: abc'
#define A foo
diff --git a/test/Preprocessor/macro_fn_preexpand.c b/test/Preprocessor/macro_fn_preexpand.c
index a392263aef43..ac3b3530dc82 100644
--- a/test/Preprocessor/macro_fn_preexpand.c
+++ b/test/Preprocessor/macro_fn_preexpand.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -E | grep 'pre: 1 1 X' &&
+// RUN: clang-cc %s -E | grep 'pre: 1 1 X'
// RUN: clang-cc %s -E | grep 'nopre: 1A(X)'
/* Preexpansion of argument. */
diff --git a/test/Preprocessor/macro_fn_varargs_iso.c b/test/Preprocessor/macro_fn_varargs_iso.c
index 78ad212405cf..b1e5c5282332 100644
--- a/test/Preprocessor/macro_fn_varargs_iso.c
+++ b/test/Preprocessor/macro_fn_varargs_iso.c
@@ -1,6 +1,6 @@
-// RUN: clang-cc -E %s | grep 'foo{a, b, c, d, e}' &&
-// RUN: clang-cc -E %s | grep 'foo2{d, C, B}' &&
+// RUN: clang-cc -E %s | grep 'foo{a, b, c, d, e}'
+// RUN: clang-cc -E %s | grep 'foo2{d, C, B}'
// RUN: clang-cc -E %s | grep 'foo2{d,e, C, B}'
#define va1(...) foo{a, __VA_ARGS__, e}
diff --git a/test/Preprocessor/macro_fn_varargs_named.c b/test/Preprocessor/macro_fn_varargs_named.c
index c2841b1574b1..94770a241d2f 100644
--- a/test/Preprocessor/macro_fn_varargs_named.c
+++ b/test/Preprocessor/macro_fn_varargs_named.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -E %s | grep '^a: x$' &&
-// RUN: clang-cc -E %s | grep '^b: x y, z,h$' &&
+// RUN: clang-cc -E %s | grep '^a: x$'
+// RUN: clang-cc -E %s | grep '^b: x y, z,h$'
// RUN: clang-cc -E %s | grep '^c: foo(x)$'
#define A(b, c...) b c
diff --git a/test/Preprocessor/macro_paste_c_block_comment.c b/test/Preprocessor/macro_paste_c_block_comment.c
index 86f812421d8c..2e5a2141698e 100644
--- a/test/Preprocessor/macro_paste_c_block_comment.c
+++ b/test/Preprocessor/macro_paste_c_block_comment.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc %s -Eonly 2>&1 | grep error &&
-// RUN: clang-cc %s -Eonly 2>&1 | not grep unterminated &&
+// RUN: clang-cc %s -Eonly 2>&1 | grep error
+// RUN: clang-cc %s -Eonly 2>&1 | not grep unterminated
// RUN: clang-cc %s -Eonly 2>&1 | not grep scratch
#define COMM / ## *
diff --git a/test/Preprocessor/macro_paste_commaext.c b/test/Preprocessor/macro_paste_commaext.c
index e98849b15afc..fe9c92ab8838 100644
--- a/test/Preprocessor/macro_paste_commaext.c
+++ b/test/Preprocessor/macro_paste_commaext.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc %s -E | grep 'V);' &&
-// RUN: clang-cc %s -E | grep 'W, 1, 2);' &&
-// RUN: clang-cc %s -E | grep 'X, 1, 2);' &&
-// RUN: clang-cc %s -E | grep 'Y, );' &&
+// RUN: clang-cc %s -E | grep 'V);'
+// RUN: clang-cc %s -E | grep 'W, 1, 2);'
+// RUN: clang-cc %s -E | grep 'X, 1, 2);'
+// RUN: clang-cc %s -E | grep 'Y, );'
// RUN: clang-cc %s -E | grep 'Z, );'
#define debug(format, ...) format, ## __VA_ARGS__)
diff --git a/test/Preprocessor/macro_paste_empty.c b/test/Preprocessor/macro_paste_empty.c
index 75504bc22a78..41843cd24c76 100644
--- a/test/Preprocessor/macro_paste_empty.c
+++ b/test/Preprocessor/macro_paste_empty.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -E %s | grep 'a:Y' &&
-// RUN: clang-cc -E %s | grep 'b:Y' &&
+// RUN: clang-cc -E %s | grep 'a:Y'
+// RUN: clang-cc -E %s | grep 'b:Y'
// RUN: clang-cc -E %s | grep 'c:YY'
#define FOO(X) X ## Y
diff --git a/test/Preprocessor/macro_paste_hard.c b/test/Preprocessor/macro_paste_hard.c
index 25b6c1994b5c..adc447c39f67 100644
--- a/test/Preprocessor/macro_paste_hard.c
+++ b/test/Preprocessor/macro_paste_hard.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -E %s | grep '1: aaab 2' &&
-// RUN: clang-cc -E %s | grep '2: 2 baaa' &&
+// RUN: clang-cc -E %s | grep '1: aaab 2'
+// RUN: clang-cc -E %s | grep '2: 2 baaa'
// RUN: clang-cc -E %s | grep '3: 2 xx'
#define a(n) aaa ## n
diff --git a/test/Preprocessor/macro_rescan.c b/test/Preprocessor/macro_rescan.c
index 17b4dc2756fd..c6a807ae4e02 100644
--- a/test/Preprocessor/macro_rescan.c
+++ b/test/Preprocessor/macro_rescan.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -E %s | grep 'ei_1 = (17 +1);' &&
+// RUN: clang-cc -E %s | grep 'ei_1 = (17 +1);'
// RUN: clang-cc -E %s | grep 'ei_2 = (M1)(17);'
#define M1(a) (a+1)
diff --git a/test/Preprocessor/macro_rescan2.c b/test/Preprocessor/macro_rescan2.c
index 6914ae0ac5f3..9c198c995a54 100644
--- a/test/Preprocessor/macro_rescan2.c
+++ b/test/Preprocessor/macro_rescan2.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -E | grep 'a: 2\*f(9)' &&
+// RUN: clang-cc %s -E | grep 'a: 2\*f(9)'
// RUN: clang-cc %s -E | grep 'b: 2\*9\*g'
#define f(a) a*g
diff --git a/test/Preprocessor/objc-pp.m b/test/Preprocessor/objc-pp.m
index 4ab2f07cef26..977789e38f1c 100644
--- a/test/Preprocessor/objc-pp.m
+++ b/test/Preprocessor/objc-pp.m
@@ -1,4 +1,4 @@
// RUN: clang-cc %s -fsyntax-only -verify -pedantic
-#import <limits.h> // no warning on #import in objc mode.
+#import <stdint.h> // no warning on #import in objc mode.
diff --git a/test/Preprocessor/optimize.c b/test/Preprocessor/optimize.c
index 46df2a66b920..973d27f8c8b5 100644
--- a/test/Preprocessor/optimize.c
+++ b/test/Preprocessor/optimize.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -Eonly %s -DOPT_O2 -O2 -verify &&
+// RUN: clang-cc -Eonly %s -DOPT_O2 -O2 -verify
#ifdef OPT_O2
#ifndef __OPTIMIZE__
#error "__OPTIMIZE__ not defined"
@@ -8,7 +8,7 @@
#endif
#endif
-// RUN: clang-cc -Eonly %s -DOPT_O0 -O0 -verify &&
+// RUN: clang-cc -Eonly %s -DOPT_O0 -O0 -verify
#ifdef OPT_O0
#ifdef __OPTIMIZE__
#error "__OPTIMIZE__ defined"
diff --git a/test/Preprocessor/pic.c b/test/Preprocessor/pic.c
index 1cddaa1a91e6..b8068faac8c0 100644
--- a/test/Preprocessor/pic.c
+++ b/test/Preprocessor/pic.c
@@ -1,10 +1,9 @@
-// RUN: clang -ccc-host-triple i386-unknown-unknown -static -dM -E -o %t %s &&
-// RUN: grep '#define __PIC__' %t | count 0 &&
-// RUN: grep '#define __pic__' %t | count 0 &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -fpic -dM -E -o %t %s &&
-// RUN: grep '#define __PIC__ 1' %t | count 1 &&
-// RUN: grep '#define __pic__ 1' %t | count 1 &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -fPIC -dM -E -o %t %s &&
-// RUN: grep '#define __PIC__ 2' %t | count 1 &&
-// RUN: grep '#define __pic__ 2' %t | count 1 &&
-// RUN: true
+// RUN: clang -ccc-host-triple i386-unknown-unknown -static -dM -E -o %t %s
+// RUN: grep '#define __PIC__' %t | count 0
+// RUN: grep '#define __pic__' %t | count 0
+// RUN: clang -ccc-host-triple i386-unknown-unknown -fpic -dM -E -o %t %s
+// RUN: grep '#define __PIC__ 1' %t | count 1
+// RUN: grep '#define __pic__ 1' %t | count 1
+// RUN: clang -ccc-host-triple i386-unknown-unknown -fPIC -dM -E -o %t %s
+// RUN: grep '#define __PIC__ 2' %t | count 1
+// RUN: grep '#define __pic__ 2' %t | count 1
diff --git a/test/Preprocessor/pragma_unknown.c b/test/Preprocessor/pragma_unknown.c
index 16bf43b3f42e..c0355e7a9614 100644
--- a/test/Preprocessor/pragma_unknown.c
+++ b/test/Preprocessor/pragma_unknown.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -E %s | grep '#pragma foo bar' &&
+// RUN: clang-cc -E %s | grep '#pragma foo bar'
// RUN: clang-cc -fsyntax-only -Wunknown-pragmas -verify %s
// GCC doesn't expand macro args for unrecognized pragmas.
diff --git a/test/Preprocessor/print_line_track.c b/test/Preprocessor/print_line_track.c
index 539433d1af04..553c1861023a 100644
--- a/test/Preprocessor/print_line_track.c
+++ b/test/Preprocessor/print_line_track.c
@@ -1,7 +1,7 @@
-/* RUN: clang-cc -E %s | grep 'a 3' &&
- * RUN: clang-cc -E %s | grep 'b 16' &&
- * RUN: clang-cc -E -P %s | grep 'a 3' &&
- * RUN: clang-cc -E -P %s | grep 'b 16' &&
+/* RUN: clang-cc -E %s | grep 'a 3'
+ * RUN: clang-cc -E %s | grep 'b 16'
+ * RUN: clang-cc -E -P %s | grep 'a 3'
+ * RUN: clang-cc -E -P %s | grep 'b 16'
* RUN: clang-cc -E %s | not grep '# 0 '
* PR1848
* PR3437
diff --git a/test/Preprocessor/stdint.c b/test/Preprocessor/stdint.c
index d47b51dbc7b7..641f704e51d9 100644
--- a/test/Preprocessor/stdint.c
+++ b/test/Preprocessor/stdint.c
@@ -1,20 +1,20 @@
-// RUN: clang-cc -E -ffreestanding -triple=arm-none-none %s | FileCheck -check-prefix ARM %s &&
+// RUN: clang-cc -E -ffreestanding -triple=arm-none-none %s | FileCheck -check-prefix ARM %s
//
-// ARM:typedef long long int int64_t;
+// ARM:typedef signed long long int int64_t;
// ARM:typedef unsigned long long int uint64_t;
// ARM:typedef int64_t int_least64_t;
// ARM:typedef uint64_t uint_least64_t;
// ARM:typedef int64_t int_fast64_t;
// ARM:typedef uint64_t uint_fast64_t;
//
-// ARM:typedef int int32_t;
+// ARM:typedef signed int int32_t;
// ARM:typedef unsigned int uint32_t;
// ARM:typedef int32_t int_least32_t;
// ARM:typedef uint32_t uint_least32_t;
// ARM:typedef int32_t int_fast32_t;
// ARM:typedef uint32_t uint_fast32_t;
//
-// ARM:typedef short int16_t;
+// ARM:typedef signed short int16_t;
// ARM:typedef unsigned short uint16_t;
// ARM:typedef int16_t int_least16_t;
// ARM:typedef uint16_t uint_least16_t;
@@ -35,22 +35,22 @@
// ARM:typedef long long unsigned int uintmax_t;
//
// ARM:INT8_MAX_ 127
-// ARM:INT8_MIN_ (-128)
+// ARM:INT8_MIN_ (-127 -1)
// ARM:UINT8_MAX_ 255
-// ARM:INT_LEAST8_MIN_ (-128)
+// ARM:INT_LEAST8_MIN_ (-127 -1)
// ARM:INT_LEAST8_MAX_ 127
// ARM:UINT_LEAST8_MAX_ 255
-// ARM:INT_FAST8_MIN_ (-128)
+// ARM:INT_FAST8_MIN_ (-127 -1)
// ARM:INT_FAST8_MAX_ 127
// ARM:UINT_FAST8_MAX_ 255
//
// ARM:INT16_MAX_ 32767
-// ARM:INT16_MIN_ (-32768)
+// ARM:INT16_MIN_ (-32767 -1)
// ARM:UINT16_MAX_ 65535
-// ARM:INT_LEAST16_MIN_ (-32768)
+// ARM:INT_LEAST16_MIN_ (-32767 -1)
// ARM:INT_LEAST16_MAX_ 32767
// ARM:UINT_LEAST16_MAX_ 65535
-// ARM:INT_FAST16_MIN_ (-32768)
+// ARM:INT_FAST16_MIN_ (-32767 -1)
// ARM:INT_FAST16_MAX_ 32767
// ARM:UINT_FAST16_MAX_ 65535
//
@@ -93,36 +93,36 @@
// ARM:WCHAR_MAX_ 2147483647
// ARM:WCHAR_MIN_ (-2147483647 -1)
//
-// ARM:INT8_C_(0) (0)
-// ARM:UINT8_C_(0) (0U)
-// ARM:INT16_C_(0) (0)
-// ARM:UINT16_C_(0) (0U)
-// ARM:INT32_C_(0) (0)
-// ARM:UINT32_C_(0) (0U)
-// ARM:INT64_C_(0) (0LL)
-// ARM:UINT64_C_(0) (0ULL)
+// ARM:INT8_C_(0) 0
+// ARM:UINT8_C_(0) 0U
+// ARM:INT16_C_(0) 0
+// ARM:UINT16_C_(0) 0U
+// ARM:INT32_C_(0) 0
+// ARM:UINT32_C_(0) 0U
+// ARM:INT64_C_(0) 0LL
+// ARM:UINT64_C_(0) 0ULL
//
-// ARM:INTMAX_C_(0) (0LL)
-// ARM:UINTMAX_C_(0) (0ULL)
+// ARM:INTMAX_C_(0) 0LL
+// ARM:UINTMAX_C_(0) 0ULL
//
//
-// RUN: clang-cc -E -ffreestanding -triple=bfin-none-none %s | FileCheck -check-prefix BFIN %s &&
+// RUN: clang-cc -E -ffreestanding -triple=bfin-none-none %s | FileCheck -check-prefix BFIN %s
//
-// BFIN:typedef long long int int64_t;
+// BFIN:typedef signed long long int int64_t;
// BFIN:typedef unsigned long long int uint64_t;
// BFIN:typedef int64_t int_least64_t;
// BFIN:typedef uint64_t uint_least64_t;
// BFIN:typedef int64_t int_fast64_t;
// BFIN:typedef uint64_t uint_fast64_t;
//
-// BFIN:typedef int int32_t;
+// BFIN:typedef signed int int32_t;
// BFIN:typedef unsigned int uint32_t;
// BFIN:typedef int32_t int_least32_t;
// BFIN:typedef uint32_t uint_least32_t;
// BFIN:typedef int32_t int_fast32_t;
// BFIN:typedef uint32_t uint_fast32_t;
//
-// BFIN:typedef short int16_t;
+// BFIN:typedef signed short int16_t;
// BFIN:typedef unsigned short uint16_t;
// BFIN:typedef int16_t int_least16_t;
// BFIN:typedef uint16_t uint_least16_t;
@@ -143,22 +143,22 @@
// BFIN:typedef long long unsigned int uintmax_t;
//
// BFIN:INT8_MAX_ 127
-// BFIN:INT8_MIN_ (-128)
+// BFIN:INT8_MIN_ (-127 -1)
// BFIN:UINT8_MAX_ 255
-// BFIN:INT_LEAST8_MIN_ (-128)
+// BFIN:INT_LEAST8_MIN_ (-127 -1)
// BFIN:INT_LEAST8_MAX_ 127
// BFIN:UINT_LEAST8_MAX_ 255
-// BFIN:INT_FAST8_MIN_ (-128)
+// BFIN:INT_FAST8_MIN_ (-127 -1)
// BFIN:INT_FAST8_MAX_ 127
// BFIN:UINT_FAST8_MAX_ 255
//
// BFIN:INT16_MAX_ 32767
-// BFIN:INT16_MIN_ (-32768)
+// BFIN:INT16_MIN_ (-32767 -1)
// BFIN:UINT16_MAX_ 65535
-// BFIN:INT_LEAST16_MIN_ (-32768)
+// BFIN:INT_LEAST16_MIN_ (-32767 -1)
// BFIN:INT_LEAST16_MAX_ 32767
// BFIN:UINT_LEAST16_MAX_ 65535
-// BFIN:INT_FAST16_MIN_ (-32768)
+// BFIN:INT_FAST16_MIN_ (-32767 -1)
// BFIN:INT_FAST16_MAX_ 32767
// BFIN:UINT_FAST16_MAX_ 65535
//
@@ -201,36 +201,36 @@
// BFIN:WCHAR_MAX_ 2147483647
// BFIN:WCHAR_MIN_ (-2147483647 -1)
//
-// BFIN:INT8_C_(0) (0)
-// BFIN:UINT8_C_(0) (0U)
-// BFIN:INT16_C_(0) (0)
-// BFIN:UINT16_C_(0) (0U)
-// BFIN:INT32_C_(0) (0)
-// BFIN:UINT32_C_(0) (0U)
-// BFIN:INT64_C_(0) (0LL)
-// BFIN:UINT64_C_(0) (0ULL)
+// BFIN:INT8_C_(0) 0
+// BFIN:UINT8_C_(0) 0U
+// BFIN:INT16_C_(0) 0
+// BFIN:UINT16_C_(0) 0U
+// BFIN:INT32_C_(0) 0
+// BFIN:UINT32_C_(0) 0U
+// BFIN:INT64_C_(0) 0LL
+// BFIN:UINT64_C_(0) 0ULL
//
-// BFIN:INTMAX_C_(0) (0LL)
-// BFIN:UINTMAX_C_(0) (0ULL)
+// BFIN:INTMAX_C_(0) 0LL
+// BFIN:UINTMAX_C_(0) 0ULL
//
//
-// RUN: clang-cc -E -ffreestanding -triple=i386-none-none %s | FileCheck -check-prefix I386 %s &&
+// RUN: clang-cc -E -ffreestanding -triple=i386-none-none %s | FileCheck -check-prefix I386 %s
//
-// I386:typedef long long int int64_t;
+// I386:typedef signed long long int int64_t;
// I386:typedef unsigned long long int uint64_t;
// I386:typedef int64_t int_least64_t;
// I386:typedef uint64_t uint_least64_t;
// I386:typedef int64_t int_fast64_t;
// I386:typedef uint64_t uint_fast64_t;
//
-// I386:typedef int int32_t;
+// I386:typedef signed int int32_t;
// I386:typedef unsigned int uint32_t;
// I386:typedef int32_t int_least32_t;
// I386:typedef uint32_t uint_least32_t;
// I386:typedef int32_t int_fast32_t;
// I386:typedef uint32_t uint_fast32_t;
//
-// I386:typedef short int16_t;
+// I386:typedef signed short int16_t;
// I386:typedef unsigned short uint16_t;
// I386:typedef int16_t int_least16_t;
// I386:typedef uint16_t uint_least16_t;
@@ -251,22 +251,22 @@
// I386:typedef long long unsigned int uintmax_t;
//
// I386:INT8_MAX_ 127
-// I386:INT8_MIN_ (-128)
+// I386:INT8_MIN_ (-127 -1)
// I386:UINT8_MAX_ 255
-// I386:INT_LEAST8_MIN_ (-128)
+// I386:INT_LEAST8_MIN_ (-127 -1)
// I386:INT_LEAST8_MAX_ 127
// I386:UINT_LEAST8_MAX_ 255
-// I386:INT_FAST8_MIN_ (-128)
+// I386:INT_FAST8_MIN_ (-127 -1)
// I386:INT_FAST8_MAX_ 127
// I386:UINT_FAST8_MAX_ 255
//
// I386:INT16_MAX_ 32767
-// I386:INT16_MIN_ (-32768)
+// I386:INT16_MIN_ (-32767 -1)
// I386:UINT16_MAX_ 65535
-// I386:INT_LEAST16_MIN_ (-32768)
+// I386:INT_LEAST16_MIN_ (-32767 -1)
// I386:INT_LEAST16_MAX_ 32767
// I386:UINT_LEAST16_MAX_ 65535
-// I386:INT_FAST16_MIN_ (-32768)
+// I386:INT_FAST16_MIN_ (-32767 -1)
// I386:INT_FAST16_MAX_ 32767
// I386:UINT_FAST16_MAX_ 65535
//
@@ -309,28 +309,28 @@
// I386:WCHAR_MAX_ 2147483647
// I386:WCHAR_MIN_ (-2147483647 -1)
//
-// I386:INT8_C_(0) (0)
-// I386:UINT8_C_(0) (0U)
-// I386:INT16_C_(0) (0)
-// I386:UINT16_C_(0) (0U)
-// I386:INT32_C_(0) (0)
-// I386:UINT32_C_(0) (0U)
-// I386:INT64_C_(0) (0LL)
-// I386:UINT64_C_(0) (0ULL)
+// I386:INT8_C_(0) 0
+// I386:UINT8_C_(0) 0U
+// I386:INT16_C_(0) 0
+// I386:UINT16_C_(0) 0U
+// I386:INT32_C_(0) 0
+// I386:UINT32_C_(0) 0U
+// I386:INT64_C_(0) 0LL
+// I386:UINT64_C_(0) 0ULL
//
-// I386:INTMAX_C_(0) (0LL)
-// I386:UINTMAX_C_(0) (0ULL)
+// I386:INTMAX_C_(0) 0LL
+// I386:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=msp430-none-none %s | FileCheck -check-prefix MSP430 %s &&
+// RUN: clang-cc -E -ffreestanding -triple=msp430-none-none %s | FileCheck -check-prefix MSP430 %s
//
-// MSP430:typedef long long int32_t;
-// MSP430:typedef unsigned long long uint32_t;
+// MSP430:typedef signed long int int32_t;
+// MSP430:typedef unsigned long int uint32_t;
// MSP430:typedef int32_t int_least32_t;
// MSP430:typedef uint32_t uint_least32_t;
// MSP430:typedef int32_t int_fast32_t;
// MSP430:typedef uint32_t uint_fast32_t;
//
-// MSP430:typedef short int16_t;
+// MSP430:typedef signed short int16_t;
// MSP430:typedef unsigned short uint16_t;
// MSP430:typedef int16_t int_least16_t;
// MSP430:typedef uint16_t uint_least16_t;
@@ -351,34 +351,34 @@
// MSP430:typedef long unsigned int uintmax_t;
//
// MSP430:INT8_MAX_ 127
-// MSP430:INT8_MIN_ (-128)
+// MSP430:INT8_MIN_ (-127 -1)
// MSP430:UINT8_MAX_ 255
-// MSP430:INT_LEAST8_MIN_ (-128)
+// MSP430:INT_LEAST8_MIN_ (-127 -1)
// MSP430:INT_LEAST8_MAX_ 127
// MSP430:UINT_LEAST8_MAX_ 255
-// MSP430:INT_FAST8_MIN_ (-128)
+// MSP430:INT_FAST8_MIN_ (-127 -1)
// MSP430:INT_FAST8_MAX_ 127
// MSP430:UINT_FAST8_MAX_ 255
//
// MSP430:INT16_MAX_ 32767
-// MSP430:INT16_MIN_ (-32768)
+// MSP430:INT16_MIN_ (-32767 -1)
// MSP430:UINT16_MAX_ 65535
-// MSP430:INT_LEAST16_MIN_ (-32768)
+// MSP430:INT_LEAST16_MIN_ (-32767 -1)
// MSP430:INT_LEAST16_MAX_ 32767
// MSP430:UINT_LEAST16_MAX_ 65535
-// MSP430:INT_FAST16_MIN_ (-32768)
+// MSP430:INT_FAST16_MIN_ (-32767 -1)
// MSP430:INT_FAST16_MAX_ 32767
// MSP430:UINT_FAST16_MAX_ 65535
//
-// MSP430:INT32_MAX_ 2147483647
-// MSP430:INT32_MIN_ (-2147483647 -1)
-// MSP430:UINT32_MAX_ 4294967295U
-// MSP430:INT_LEAST32_MIN_ (-2147483647 -1)
-// MSP430:INT_LEAST32_MAX_ 2147483647
-// MSP430:UINT_LEAST32_MAX_ 4294967295U
-// MSP430:INT_FAST32_MIN_ (-2147483647 -1)
-// MSP430:INT_FAST32_MAX_ 2147483647
-// MSP430:UINT_FAST32_MAX_ 4294967295U
+// MSP430:INT32_MAX_ 2147483647L
+// MSP430:INT32_MIN_ (-2147483647L -1)
+// MSP430:UINT32_MAX_ 4294967295UL
+// MSP430:INT_LEAST32_MIN_ (-2147483647L -1)
+// MSP430:INT_LEAST32_MAX_ 2147483647L
+// MSP430:UINT_LEAST32_MAX_ 4294967295UL
+// MSP430:INT_FAST32_MIN_ (-2147483647L -1)
+// MSP430:INT_FAST32_MAX_ 2147483647L
+// MSP430:UINT_FAST32_MAX_ 4294967295UL
//
// MSP430:INT64_MAX_ INT64_MAX
// MSP430:INT64_MIN_ INT64_MIN
@@ -390,10 +390,10 @@
// MSP430:INT_FAST64_MAX_ INT_FAST64_MAX
// MSP430:UINT_FAST64_MAX_ UINT_FAST64_MAX
//
-// MSP430:INTPTR_MIN_ (-32768)
+// MSP430:INTPTR_MIN_ (-32767 -1)
// MSP430:INTPTR_MAX_ 32767
// MSP430:UINTPTR_MAX_ 65535
-// MSP430:PTRDIFF_MIN_ (-32768)
+// MSP430:PTRDIFF_MIN_ (-32767 -1)
// MSP430:PTRDIFF_MAX_ 32767
// MSP430:SIZE_MAX_ 65535
//
@@ -401,36 +401,36 @@
// MSP430:INTMAX_MAX_ 2147483647L
// MSP430:UINTMAX_MAX_ (2147483647L*2ULL +1ULL)
//
-// MSP430:SIG_ATOMIC_MIN_ (-2147483647 -1)
-// MSP430:SIG_ATOMIC_MAX_ 2147483647
-// MSP430:WINT_MIN_ (-2147483647 -1)
-// MSP430:WINT_MAX_ 2147483647
+// MSP430:SIG_ATOMIC_MIN_ (-2147483647L -1)
+// MSP430:SIG_ATOMIC_MAX_ 2147483647L
+// MSP430:WINT_MIN_ (-2147483647L -1)
+// MSP430:WINT_MAX_ 2147483647L
//
-// MSP430:WCHAR_MAX_ 2147483647
-// MSP430:WCHAR_MIN_ (-2147483647 -1)
+// MSP430:WCHAR_MAX_ 32767
+// MSP430:WCHAR_MIN_ (-32767 -1)
//
-// MSP430:INT8_C_(0) (0)
-// MSP430:UINT8_C_(0) (0U)
-// MSP430:INT16_C_(0) (0)
-// MSP430:UINT16_C_(0) (0U)
-// MSP430:INT32_C_(0) (0)
-// MSP430:UINT32_C_(0) (0U)
+// MSP430:INT8_C_(0) 0
+// MSP430:UINT8_C_(0) 0U
+// MSP430:INT16_C_(0) 0
+// MSP430:UINT16_C_(0) 0U
+// MSP430:INT32_C_(0) 0L
+// MSP430:UINT32_C_(0) 0UL
// MSP430:INT64_C_(0) INT64_C(0)
// MSP430:UINT64_C_(0) UINT64_C(0)
//
-// MSP430:INTMAX_C_(0) (0LL)
-// MSP430:UINTMAX_C_(0) (0ULL)
+// MSP430:INTMAX_C_(0) 0LL
+// MSP430:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=pic16-none-none %s | FileCheck -check-prefix PIC16 %s &&
+// RUN: clang-cc -E -ffreestanding -triple=pic16-none-none %s | FileCheck -check-prefix PIC16 %s
//
-// PIC16:typedef long long int32_t;
-// PIC16:typedef unsigned long long uint32_t;
+// PIC16:typedef signed long int int32_t;
+// PIC16:typedef unsigned long int uint32_t;
// PIC16:typedef int32_t int_least32_t;
// PIC16:typedef uint32_t uint_least32_t;
// PIC16:typedef int32_t int_fast32_t;
// PIC16:typedef uint32_t uint_fast32_t;
//
-// PIC16:typedef short int16_t;
+// PIC16:typedef signed short int16_t;
// PIC16:typedef unsigned short uint16_t;
// PIC16:typedef int16_t int_least16_t;
// PIC16:typedef uint16_t uint_least16_t;
@@ -451,34 +451,34 @@
// PIC16:typedef long unsigned int uintmax_t;
//
// PIC16:INT8_MAX_ 127
-// PIC16:INT8_MIN_ (-128)
+// PIC16:INT8_MIN_ (-127 -1)
// PIC16:UINT8_MAX_ 255
-// PIC16:INT_LEAST8_MIN_ (-128)
+// PIC16:INT_LEAST8_MIN_ (-127 -1)
// PIC16:INT_LEAST8_MAX_ 127
// PIC16:UINT_LEAST8_MAX_ 255
-// PIC16:INT_FAST8_MIN_ (-128)
+// PIC16:INT_FAST8_MIN_ (-127 -1)
// PIC16:INT_FAST8_MAX_ 127
// PIC16:UINT_FAST8_MAX_ 255
//
// PIC16:INT16_MAX_ 32767
-// PIC16:INT16_MIN_ (-32768)
+// PIC16:INT16_MIN_ (-32767 -1)
// PIC16:UINT16_MAX_ 65535
-// PIC16:INT_LEAST16_MIN_ (-32768)
+// PIC16:INT_LEAST16_MIN_ (-32767 -1)
// PIC16:INT_LEAST16_MAX_ 32767
// PIC16:UINT_LEAST16_MAX_ 65535
-// PIC16:INT_FAST16_MIN_ (-32768)
+// PIC16:INT_FAST16_MIN_ (-32767 -1)
// PIC16:INT_FAST16_MAX_ 32767
// PIC16:UINT_FAST16_MAX_ 65535
//
-// PIC16:INT32_MAX_ 2147483647
-// PIC16:INT32_MIN_ (-2147483647 -1)
-// PIC16:UINT32_MAX_ 4294967295U
-// PIC16:INT_LEAST32_MIN_ (-2147483647 -1)
-// PIC16:INT_LEAST32_MAX_ 2147483647
-// PIC16:UINT_LEAST32_MAX_ 4294967295U
-// PIC16:INT_FAST32_MIN_ (-2147483647 -1)
-// PIC16:INT_FAST32_MAX_ 2147483647
-// PIC16:UINT_FAST32_MAX_ 4294967295U
+// PIC16:INT32_MAX_ 2147483647L
+// PIC16:INT32_MIN_ (-2147483647L -1)
+// PIC16:UINT32_MAX_ 4294967295UL
+// PIC16:INT_LEAST32_MIN_ (-2147483647L -1)
+// PIC16:INT_LEAST32_MAX_ 2147483647L
+// PIC16:UINT_LEAST32_MAX_ 4294967295UL
+// PIC16:INT_FAST32_MIN_ (-2147483647L -1)
+// PIC16:INT_FAST32_MAX_ 2147483647L
+// PIC16:UINT_FAST32_MAX_ 4294967295UL
//
// PIC16:INT64_MAX_ INT64_MAX
// PIC16:INT64_MIN_ INT64_MIN
@@ -490,10 +490,10 @@
// PIC16:INT_FAST64_MAX_ INT_FAST64_MAX
// PIC16:UINT_FAST64_MAX_ UINT_FAST64_MAX
//
-// PIC16:INTPTR_MIN_ (-32768)
+// PIC16:INTPTR_MIN_ (-32767 -1)
// PIC16:INTPTR_MAX_ 32767
// PIC16:UINTPTR_MAX_ 65535
-// PIC16:PTRDIFF_MIN_ (-32768)
+// PIC16:PTRDIFF_MIN_ (-32767 -1)
// PIC16:PTRDIFF_MAX_ 32767
// PIC16:SIZE_MAX_ 65535
//
@@ -501,43 +501,43 @@
// PIC16:INTMAX_MAX_ 2147483647L
// PIC16:UINTMAX_MAX_ (2147483647L*2ULL +1ULL)
//
-// PIC16:SIG_ATOMIC_MIN_ (-2147483647 -1)
-// PIC16:SIG_ATOMIC_MAX_ 2147483647
-// PIC16:WINT_MIN_ (-2147483647 -1)
-// PIC16:WINT_MAX_ 2147483647
+// PIC16:SIG_ATOMIC_MIN_ (-2147483647L -1)
+// PIC16:SIG_ATOMIC_MAX_ 2147483647L
+// PIC16:WINT_MIN_ (-2147483647L -1)
+// PIC16:WINT_MAX_ 2147483647L
//
-// PIC16:WCHAR_MAX_ 2147483647
-// PIC16:WCHAR_MIN_ (-2147483647 -1)
+// PIC16:WCHAR_MAX_ 32767
+// PIC16:WCHAR_MIN_ (-32767 -1)
//
-// PIC16:INT8_C_(0) (0)
-// PIC16:UINT8_C_(0) (0U)
-// PIC16:INT16_C_(0) (0)
-// PIC16:UINT16_C_(0) (0U)
-// PIC16:INT32_C_(0) (0)
-// PIC16:UINT32_C_(0) (0U)
+// PIC16:INT8_C_(0) 0
+// PIC16:UINT8_C_(0) 0U
+// PIC16:INT16_C_(0) 0
+// PIC16:UINT16_C_(0) 0U
+// PIC16:INT32_C_(0) 0L
+// PIC16:UINT32_C_(0) 0UL
// PIC16:INT64_C_(0) INT64_C(0)
// PIC16:UINT64_C_(0) UINT64_C(0)
//
-// PIC16:INTMAX_C_(0) (0LL)
-// PIC16:UINTMAX_C_(0) (0ULL)
+// PIC16:INTMAX_C_(0) 0LL
+// PIC16:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=powerpc64-none-none %s | FileCheck -check-prefix PPC64 %s &&
+// RUN: clang-cc -E -ffreestanding -triple=powerpc64-none-none %s | FileCheck -check-prefix PPC64 %s
//
-// PPC64:typedef long int int64_t;
+// PPC64:typedef signed long int int64_t;
// PPC64:typedef unsigned long int uint64_t;
// PPC64:typedef int64_t int_least64_t;
// PPC64:typedef uint64_t uint_least64_t;
// PPC64:typedef int64_t int_fast64_t;
// PPC64:typedef uint64_t uint_fast64_t;
//
-// PPC64:typedef int int32_t;
+// PPC64:typedef signed int int32_t;
// PPC64:typedef unsigned int uint32_t;
// PPC64:typedef int32_t int_least32_t;
// PPC64:typedef uint32_t uint_least32_t;
// PPC64:typedef int32_t int_fast32_t;
// PPC64:typedef uint32_t uint_fast32_t;
//
-// PPC64:typedef short int16_t;
+// PPC64:typedef signed short int16_t;
// PPC64:typedef unsigned short uint16_t;
// PPC64:typedef int16_t int_least16_t;
// PPC64:typedef uint16_t uint_least16_t;
@@ -558,22 +558,22 @@
// PPC64:typedef long unsigned int uintmax_t;
//
// PPC64:INT8_MAX_ 127
-// PPC64:INT8_MIN_ (-128)
+// PPC64:INT8_MIN_ (-127 -1)
// PPC64:UINT8_MAX_ 255
-// PPC64:INT_LEAST8_MIN_ (-128)
+// PPC64:INT_LEAST8_MIN_ (-127 -1)
// PPC64:INT_LEAST8_MAX_ 127
// PPC64:UINT_LEAST8_MAX_ 255
-// PPC64:INT_FAST8_MIN_ (-128)
+// PPC64:INT_FAST8_MIN_ (-127 -1)
// PPC64:INT_FAST8_MAX_ 127
// PPC64:UINT_FAST8_MAX_ 255
//
// PPC64:INT16_MAX_ 32767
-// PPC64:INT16_MIN_ (-32768)
+// PPC64:INT16_MIN_ (-32767 -1)
// PPC64:UINT16_MAX_ 65535
-// PPC64:INT_LEAST16_MIN_ (-32768)
+// PPC64:INT_LEAST16_MIN_ (-32767 -1)
// PPC64:INT_LEAST16_MAX_ 32767
// PPC64:UINT_LEAST16_MAX_ 65535
-// PPC64:INT_FAST16_MIN_ (-32768)
+// PPC64:INT_FAST16_MIN_ (-32767 -1)
// PPC64:INT_FAST16_MAX_ 32767
// PPC64:UINT_FAST16_MAX_ 65535
//
@@ -587,22 +587,22 @@
// PPC64:INT_FAST32_MAX_ 2147483647
// PPC64:UINT_FAST32_MAX_ 4294967295U
//
-// PPC64:INT64_MAX_ 9223372036854775807LL
-// PPC64:INT64_MIN_ (-9223372036854775807LL -1)
-// PPC64:UINT64_MAX_ 18446744073709551615ULL
-// PPC64:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
-// PPC64:INT_LEAST64_MAX_ 9223372036854775807LL
-// PPC64:UINT_LEAST64_MAX_ 18446744073709551615ULL
-// PPC64:INT_FAST64_MIN_ (-9223372036854775807LL -1)
-// PPC64:INT_FAST64_MAX_ 9223372036854775807LL
-// PPC64:UINT_FAST64_MAX_ 18446744073709551615ULL
-//
-// PPC64:INTPTR_MIN_ (-9223372036854775807LL -1)
-// PPC64:INTPTR_MAX_ 9223372036854775807LL
-// PPC64:UINTPTR_MAX_ 18446744073709551615ULL
-// PPC64:PTRDIFF_MIN_ (-9223372036854775807LL -1)
-// PPC64:PTRDIFF_MAX_ 9223372036854775807LL
-// PPC64:SIZE_MAX_ 18446744073709551615ULL
+// PPC64:INT64_MAX_ 9223372036854775807L
+// PPC64:INT64_MIN_ (-9223372036854775807L -1)
+// PPC64:UINT64_MAX_ 18446744073709551615UL
+// PPC64:INT_LEAST64_MIN_ (-9223372036854775807L -1)
+// PPC64:INT_LEAST64_MAX_ 9223372036854775807L
+// PPC64:UINT_LEAST64_MAX_ 18446744073709551615UL
+// PPC64:INT_FAST64_MIN_ (-9223372036854775807L -1)
+// PPC64:INT_FAST64_MAX_ 9223372036854775807L
+// PPC64:UINT_FAST64_MAX_ 18446744073709551615UL
+//
+// PPC64:INTPTR_MIN_ (-9223372036854775807L -1)
+// PPC64:INTPTR_MAX_ 9223372036854775807L
+// PPC64:UINTPTR_MAX_ 18446744073709551615UL
+// PPC64:PTRDIFF_MIN_ (-9223372036854775807L -1)
+// PPC64:PTRDIFF_MAX_ 9223372036854775807L
+// PPC64:SIZE_MAX_ 18446744073709551615UL
//
// PPC64:INTMAX_MIN_ (-9223372036854775807L -1)
// PPC64:INTMAX_MAX_ 9223372036854775807L
@@ -616,36 +616,36 @@
// PPC64:WCHAR_MAX_ 2147483647
// PPC64:WCHAR_MIN_ (-2147483647 -1)
//
-// PPC64:INT8_C_(0) (0)
-// PPC64:UINT8_C_(0) (0U)
-// PPC64:INT16_C_(0) (0)
-// PPC64:UINT16_C_(0) (0U)
-// PPC64:INT32_C_(0) (0)
-// PPC64:UINT32_C_(0) (0U)
-// PPC64:INT64_C_(0) (0LL)
-// PPC64:UINT64_C_(0) (0ULL)
+// PPC64:INT8_C_(0) 0
+// PPC64:UINT8_C_(0) 0U
+// PPC64:INT16_C_(0) 0
+// PPC64:UINT16_C_(0) 0U
+// PPC64:INT32_C_(0) 0
+// PPC64:UINT32_C_(0) 0U
+// PPC64:INT64_C_(0) 0L
+// PPC64:UINT64_C_(0) 0UL
//
-// PPC64:INTMAX_C_(0) (0LL)
-// PPC64:UINTMAX_C_(0) (0ULL)
+// PPC64:INTMAX_C_(0) 0LL
+// PPC64:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=powerpc-none-none %s | FileCheck -check-prefix PPC %s &&
+// RUN: clang-cc -E -ffreestanding -triple=powerpc-none-none %s | FileCheck -check-prefix PPC %s
//
//
-// PPC:typedef long long int int64_t;
+// PPC:typedef signed long long int int64_t;
// PPC:typedef unsigned long long int uint64_t;
// PPC:typedef int64_t int_least64_t;
// PPC:typedef uint64_t uint_least64_t;
// PPC:typedef int64_t int_fast64_t;
// PPC:typedef uint64_t uint_fast64_t;
//
-// PPC:typedef int int32_t;
+// PPC:typedef signed int int32_t;
// PPC:typedef unsigned int uint32_t;
// PPC:typedef int32_t int_least32_t;
// PPC:typedef uint32_t uint_least32_t;
// PPC:typedef int32_t int_fast32_t;
// PPC:typedef uint32_t uint_fast32_t;
//
-// PPC:typedef short int16_t;
+// PPC:typedef signed short int16_t;
// PPC:typedef unsigned short uint16_t;
// PPC:typedef int16_t int_least16_t;
// PPC:typedef uint16_t uint_least16_t;
@@ -666,22 +666,22 @@
// PPC:typedef long long unsigned int uintmax_t;
//
// PPC:INT8_MAX_ 127
-// PPC:INT8_MIN_ (-128)
+// PPC:INT8_MIN_ (-127 -1)
// PPC:UINT8_MAX_ 255
-// PPC:INT_LEAST8_MIN_ (-128)
+// PPC:INT_LEAST8_MIN_ (-127 -1)
// PPC:INT_LEAST8_MAX_ 127
// PPC:UINT_LEAST8_MAX_ 255
-// PPC:INT_FAST8_MIN_ (-128)
+// PPC:INT_FAST8_MIN_ (-127 -1)
// PPC:INT_FAST8_MAX_ 127
// PPC:UINT_FAST8_MAX_ 255
//
// PPC:INT16_MAX_ 32767
-// PPC:INT16_MIN_ (-32768)
+// PPC:INT16_MIN_ (-32767 -1)
// PPC:UINT16_MAX_ 65535
-// PPC:INT_LEAST16_MIN_ (-32768)
+// PPC:INT_LEAST16_MIN_ (-32767 -1)
// PPC:INT_LEAST16_MAX_ 32767
// PPC:UINT_LEAST16_MAX_ 65535
-// PPC:INT_FAST16_MIN_ (-32768)
+// PPC:INT_FAST16_MIN_ (-32767 -1)
// PPC:INT_FAST16_MAX_ 32767
// PPC:UINT_FAST16_MAX_ 65535
//
@@ -724,35 +724,35 @@
// PPC:WCHAR_MAX_ 2147483647
// PPC:WCHAR_MIN_ (-2147483647 -1)
//
-// PPC:INT8_C_(0) (0)
-// PPC:UINT8_C_(0) (0U)
-// PPC:INT16_C_(0) (0)
-// PPC:UINT16_C_(0) (0U)
-// PPC:INT32_C_(0) (0)
-// PPC:UINT32_C_(0) (0U)
-// PPC:INT64_C_(0) (0LL)
-// PPC:UINT64_C_(0) (0ULL)
+// PPC:INT8_C_(0) 0
+// PPC:UINT8_C_(0) 0U
+// PPC:INT16_C_(0) 0
+// PPC:UINT16_C_(0) 0U
+// PPC:INT32_C_(0) 0
+// PPC:UINT32_C_(0) 0U
+// PPC:INT64_C_(0) 0LL
+// PPC:UINT64_C_(0) 0ULL
//
-// PPC:INTMAX_C_(0) (0LL)
-// PPC:UINTMAX_C_(0) (0ULL)
+// PPC:INTMAX_C_(0) 0LL
+// PPC:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=s390x-none-none %s | FileCheck -check-prefix S390X %s &&
+// RUN: clang-cc -E -ffreestanding -triple=s390x-none-none %s | FileCheck -check-prefix S390X %s
//
-// S390X:typedef long long int int64_t;
-// S390X:typedef unsigned long long int uint64_t;
+// S390X:typedef signed long int int64_t;
+// S390X:typedef unsigned long int uint64_t;
// S390X:typedef int64_t int_least64_t;
// S390X:typedef uint64_t uint_least64_t;
// S390X:typedef int64_t int_fast64_t;
// S390X:typedef uint64_t uint_fast64_t;
//
-// S390X:typedef int int32_t;
+// S390X:typedef signed int int32_t;
// S390X:typedef unsigned int uint32_t;
// S390X:typedef int32_t int_least32_t;
// S390X:typedef uint32_t uint_least32_t;
// S390X:typedef int32_t int_fast32_t;
// S390X:typedef uint32_t uint_fast32_t;
//
-// S390X:typedef short int16_t;
+// S390X:typedef signed short int16_t;
// S390X:typedef unsigned short uint16_t;
// S390X:typedef int16_t int_least16_t;
// S390X:typedef uint16_t uint_least16_t;
@@ -773,22 +773,22 @@
// S390X:typedef long long unsigned int uintmax_t;
//
// S390X:INT8_MAX_ 127
-// S390X:INT8_MIN_ (-128)
+// S390X:INT8_MIN_ (-127 -1)
// S390X:UINT8_MAX_ 255
-// S390X:INT_LEAST8_MIN_ (-128)
+// S390X:INT_LEAST8_MIN_ (-127 -1)
// S390X:INT_LEAST8_MAX_ 127
// S390X:UINT_LEAST8_MAX_ 255
-// S390X:INT_FAST8_MIN_ (-128)
+// S390X:INT_FAST8_MIN_ (-127 -1)
// S390X:INT_FAST8_MAX_ 127
// S390X:UINT_FAST8_MAX_ 255
//
// S390X:INT16_MAX_ 32767
-// S390X:INT16_MIN_ (-32768)
+// S390X:INT16_MIN_ (-32767 -1)
// S390X:UINT16_MAX_ 65535
-// S390X:INT_LEAST16_MIN_ (-32768)
+// S390X:INT_LEAST16_MIN_ (-32767 -1)
// S390X:INT_LEAST16_MAX_ 32767
// S390X:UINT_LEAST16_MAX_ 65535
-// S390X:INT_FAST16_MIN_ (-32768)
+// S390X:INT_FAST16_MIN_ (-32767 -1)
// S390X:INT_FAST16_MAX_ 32767
// S390X:UINT_FAST16_MAX_ 65535
//
@@ -802,22 +802,22 @@
// S390X:INT_FAST32_MAX_ 2147483647
// S390X:UINT_FAST32_MAX_ 4294967295U
//
-// S390X:INT64_MAX_ 9223372036854775807LL
-// S390X:INT64_MIN_ (-9223372036854775807LL -1)
-// S390X:UINT64_MAX_ 18446744073709551615ULL
-// S390X:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
-// S390X:INT_LEAST64_MAX_ 9223372036854775807LL
-// S390X:UINT_LEAST64_MAX_ 18446744073709551615ULL
-// S390X:INT_FAST64_MIN_ (-9223372036854775807LL -1)
-// S390X:INT_FAST64_MAX_ 9223372036854775807LL
-// S390X:UINT_FAST64_MAX_ 18446744073709551615ULL
-//
-// S390X:INTPTR_MIN_ (-9223372036854775807LL -1)
-// S390X:INTPTR_MAX_ 9223372036854775807LL
-// S390X:UINTPTR_MAX_ 18446744073709551615ULL
-// S390X:PTRDIFF_MIN_ (-9223372036854775807LL -1)
-// S390X:PTRDIFF_MAX_ 9223372036854775807LL
-// S390X:SIZE_MAX_ 18446744073709551615ULL
+// S390X:INT64_MAX_ 9223372036854775807L
+// S390X:INT64_MIN_ (-9223372036854775807L -1)
+// S390X:UINT64_MAX_ 18446744073709551615UL
+// S390X:INT_LEAST64_MIN_ (-9223372036854775807L -1)
+// S390X:INT_LEAST64_MAX_ 9223372036854775807L
+// S390X:UINT_LEAST64_MAX_ 18446744073709551615UL
+// S390X:INT_FAST64_MIN_ (-9223372036854775807L -1)
+// S390X:INT_FAST64_MAX_ 9223372036854775807L
+// S390X:UINT_FAST64_MAX_ 18446744073709551615UL
+//
+// S390X:INTPTR_MIN_ (-9223372036854775807L -1)
+// S390X:INTPTR_MAX_ 9223372036854775807L
+// S390X:UINTPTR_MAX_ 18446744073709551615UL
+// S390X:PTRDIFF_MIN_ (-9223372036854775807L -1)
+// S390X:PTRDIFF_MAX_ 9223372036854775807L
+// S390X:SIZE_MAX_ 18446744073709551615UL
//
// S390X:INTMAX_MIN_ (-9223372036854775807LL -1)
// S390X:INTMAX_MAX_ 9223372036854775807LL
@@ -831,35 +831,35 @@
// S390X:WCHAR_MAX_ 2147483647
// S390X:WCHAR_MIN_ (-2147483647 -1)
//
-// S390X:INT8_C_(0) (0)
-// S390X:UINT8_C_(0) (0U)
-// S390X:INT16_C_(0) (0)
-// S390X:UINT16_C_(0) (0U)
-// S390X:INT32_C_(0) (0)
-// S390X:UINT32_C_(0) (0U)
-// S390X:INT64_C_(0) (0LL)
-// S390X:UINT64_C_(0) (0ULL)
+// S390X:INT8_C_(0) 0
+// S390X:UINT8_C_(0) 0U
+// S390X:INT16_C_(0) 0
+// S390X:UINT16_C_(0) 0U
+// S390X:INT32_C_(0) 0
+// S390X:UINT32_C_(0) 0U
+// S390X:INT64_C_(0) 0L
+// S390X:UINT64_C_(0) 0UL
//
-// S390X:INTMAX_C_(0) (0LL)
-// S390X:UINTMAX_C_(0) (0ULL)
+// S390X:INTMAX_C_(0) 0LL
+// S390X:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=sparc-none-none %s | FileCheck -check-prefix SPARC %s &&
+// RUN: clang-cc -E -ffreestanding -triple=sparc-none-none %s | FileCheck -check-prefix SPARC %s
//
-// SPARC:typedef long long int int64_t;
+// SPARC:typedef signed long long int int64_t;
// SPARC:typedef unsigned long long int uint64_t;
// SPARC:typedef int64_t int_least64_t;
// SPARC:typedef uint64_t uint_least64_t;
// SPARC:typedef int64_t int_fast64_t;
// SPARC:typedef uint64_t uint_fast64_t;
//
-// SPARC:typedef int int32_t;
+// SPARC:typedef signed int int32_t;
// SPARC:typedef unsigned int uint32_t;
// SPARC:typedef int32_t int_least32_t;
// SPARC:typedef uint32_t uint_least32_t;
// SPARC:typedef int32_t int_fast32_t;
// SPARC:typedef uint32_t uint_fast32_t;
//
-// SPARC:typedef short int16_t;
+// SPARC:typedef signed short int16_t;
// SPARC:typedef unsigned short uint16_t;
// SPARC:typedef int16_t int_least16_t;
// SPARC:typedef uint16_t uint_least16_t;
@@ -880,22 +880,22 @@
// SPARC:typedef long long unsigned int uintmax_t;
//
// SPARC:INT8_MAX_ 127
-// SPARC:INT8_MIN_ (-128)
+// SPARC:INT8_MIN_ (-127 -1)
// SPARC:UINT8_MAX_ 255
-// SPARC:INT_LEAST8_MIN_ (-128)
+// SPARC:INT_LEAST8_MIN_ (-127 -1)
// SPARC:INT_LEAST8_MAX_ 127
// SPARC:UINT_LEAST8_MAX_ 255
-// SPARC:INT_FAST8_MIN_ (-128)
+// SPARC:INT_FAST8_MIN_ (-127 -1)
// SPARC:INT_FAST8_MAX_ 127
// SPARC:UINT_FAST8_MAX_ 255
//
// SPARC:INT16_MAX_ 32767
-// SPARC:INT16_MIN_ (-32768)
+// SPARC:INT16_MIN_ (-32767 -1)
// SPARC:UINT16_MAX_ 65535
-// SPARC:INT_LEAST16_MIN_ (-32768)
+// SPARC:INT_LEAST16_MIN_ (-32767 -1)
// SPARC:INT_LEAST16_MAX_ 32767
// SPARC:UINT_LEAST16_MAX_ 65535
-// SPARC:INT_FAST16_MIN_ (-32768)
+// SPARC:INT_FAST16_MIN_ (-32767 -1)
// SPARC:INT_FAST16_MAX_ 32767
// SPARC:UINT_FAST16_MAX_ 65535
//
@@ -938,28 +938,28 @@
// SPARC:WCHAR_MAX_ 2147483647
// SPARC:WCHAR_MIN_ (-2147483647 -1)
//
-// SPARC:INT8_C_(0) (0)
-// SPARC:UINT8_C_(0) (0U)
-// SPARC:INT16_C_(0) (0)
-// SPARC:UINT16_C_(0) (0U)
-// SPARC:INT32_C_(0) (0)
-// SPARC:UINT32_C_(0) (0U)
-// SPARC:INT64_C_(0) (0LL)
-// SPARC:UINT64_C_(0) (0ULL)
+// SPARC:INT8_C_(0) 0
+// SPARC:UINT8_C_(0) 0U
+// SPARC:INT16_C_(0) 0
+// SPARC:UINT16_C_(0) 0U
+// SPARC:INT32_C_(0) 0
+// SPARC:UINT32_C_(0) 0U
+// SPARC:INT64_C_(0) 0LL
+// SPARC:UINT64_C_(0) 0ULL
//
-// SPARC:INTMAX_C_(0) (0LL)
-// SPARC:UINTMAX_C_(0) (0ULL)
+// SPARC:INTMAX_C_(0) 0LL
+// SPARC:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=tce-none-none %s | FileCheck -check-prefix TCE %s &&
+// RUN: clang-cc -E -ffreestanding -triple=tce-none-none %s | FileCheck -check-prefix TCE %s
//
-// TCE:typedef int int32_t;
+// TCE:typedef signed int int32_t;
// TCE:typedef unsigned int uint32_t;
// TCE:typedef int32_t int_least32_t;
// TCE:typedef uint32_t uint_least32_t;
// TCE:typedef int32_t int_fast32_t;
// TCE:typedef uint32_t uint_fast32_t;
//
-// TCE:typedef short int16_t;
+// TCE:typedef signed short int16_t;
// TCE:typedef unsigned short uint16_t;
// TCE:typedef int16_t int_least16_t;
// TCE:typedef uint16_t uint_least16_t;
@@ -980,22 +980,22 @@
// TCE:typedef long unsigned int uintmax_t;
//
// TCE:INT8_MAX_ 127
-// TCE:INT8_MIN_ (-128)
+// TCE:INT8_MIN_ (-127 -1)
// TCE:UINT8_MAX_ 255
-// TCE:INT_LEAST8_MIN_ (-128)
+// TCE:INT_LEAST8_MIN_ (-127 -1)
// TCE:INT_LEAST8_MAX_ 127
// TCE:UINT_LEAST8_MAX_ 255
-// TCE:INT_FAST8_MIN_ (-128)
+// TCE:INT_FAST8_MIN_ (-127 -1)
// TCE:INT_FAST8_MAX_ 127
// TCE:UINT_FAST8_MAX_ 255
//
// TCE:INT16_MAX_ 32767
-// TCE:INT16_MIN_ (-32768)
+// TCE:INT16_MIN_ (-32767 -1)
// TCE:UINT16_MAX_ 65535
-// TCE:INT_LEAST16_MIN_ (-32768)
+// TCE:INT_LEAST16_MIN_ (-32767 -1)
// TCE:INT_LEAST16_MAX_ 32767
// TCE:UINT_LEAST16_MAX_ 65535
-// TCE:INT_FAST16_MIN_ (-32768)
+// TCE:INT_FAST16_MIN_ (-32767 -1)
// TCE:INT_FAST16_MAX_ 32767
// TCE:UINT_FAST16_MAX_ 65535
//
@@ -1038,36 +1038,36 @@
// TCE:WCHAR_MAX_ 2147483647
// TCE:WCHAR_MIN_ (-2147483647 -1)
//
-// TCE:INT8_C_(0) (0)
-// TCE:UINT8_C_(0) (0U)
-// TCE:INT16_C_(0) (0)
-// TCE:UINT16_C_(0) (0U)
-// TCE:INT32_C_(0) (0)
-// TCE:UINT32_C_(0) (0U)
+// TCE:INT8_C_(0) 0
+// TCE:UINT8_C_(0) 0U
+// TCE:INT16_C_(0) 0
+// TCE:UINT16_C_(0) 0U
+// TCE:INT32_C_(0) 0
+// TCE:UINT32_C_(0) 0U
// TCE:INT64_C_(0) INT64_C(0)
// TCE:UINT64_C_(0) UINT64_C(0)
//
-// TCE:INTMAX_C_(0) (0LL)
-// TCE:UINTMAX_C_(0) (0ULL)
+// TCE:INTMAX_C_(0) 0LL
+// TCE:UINTMAX_C_(0) 0ULL
//
-// RUN: clang-cc -E -ffreestanding -triple=x86_64-none-none %s | FileCheck -check-prefix X86_64 %s &&
+// RUN: clang-cc -E -ffreestanding -triple=x86_64-none-none %s | FileCheck -check-prefix X86_64 %s
//
//
-// X86_64:typedef long int int64_t;
+// X86_64:typedef signed long int int64_t;
// X86_64:typedef unsigned long int uint64_t;
// X86_64:typedef int64_t int_least64_t;
// X86_64:typedef uint64_t uint_least64_t;
// X86_64:typedef int64_t int_fast64_t;
// X86_64:typedef uint64_t uint_fast64_t;
//
-// X86_64:typedef int int32_t;
+// X86_64:typedef signed int int32_t;
// X86_64:typedef unsigned int uint32_t;
// X86_64:typedef int32_t int_least32_t;
// X86_64:typedef uint32_t uint_least32_t;
// X86_64:typedef int32_t int_fast32_t;
// X86_64:typedef uint32_t uint_fast32_t;
//
-// X86_64:typedef short int16_t;
+// X86_64:typedef signed short int16_t;
// X86_64:typedef unsigned short uint16_t;
// X86_64:typedef int16_t int_least16_t;
// X86_64:typedef uint16_t uint_least16_t;
@@ -1088,22 +1088,22 @@
// X86_64:typedef long unsigned int uintmax_t;
//
// X86_64:INT8_MAX_ 127
-// X86_64:INT8_MIN_ (-128)
+// X86_64:INT8_MIN_ (-127 -1)
// X86_64:UINT8_MAX_ 255
-// X86_64:INT_LEAST8_MIN_ (-128)
+// X86_64:INT_LEAST8_MIN_ (-127 -1)
// X86_64:INT_LEAST8_MAX_ 127
// X86_64:UINT_LEAST8_MAX_ 255
-// X86_64:INT_FAST8_MIN_ (-128)
+// X86_64:INT_FAST8_MIN_ (-127 -1)
// X86_64:INT_FAST8_MAX_ 127
// X86_64:UINT_FAST8_MAX_ 255
//
// X86_64:INT16_MAX_ 32767
-// X86_64:INT16_MIN_ (-32768)
+// X86_64:INT16_MIN_ (-32767 -1)
// X86_64:UINT16_MAX_ 65535
-// X86_64:INT_LEAST16_MIN_ (-32768)
+// X86_64:INT_LEAST16_MIN_ (-32767 -1)
// X86_64:INT_LEAST16_MAX_ 32767
// X86_64:UINT_LEAST16_MAX_ 65535
-// X86_64:INT_FAST16_MIN_ (-32768)
+// X86_64:INT_FAST16_MIN_ (-32767 -1)
// X86_64:INT_FAST16_MAX_ 32767
// X86_64:UINT_FAST16_MAX_ 65535
//
@@ -1117,22 +1117,22 @@
// X86_64:INT_FAST32_MAX_ 2147483647
// X86_64:UINT_FAST32_MAX_ 4294967295U
//
-// X86_64:INT64_MAX_ 9223372036854775807LL
-// X86_64:INT64_MIN_ (-9223372036854775807LL -1)
-// X86_64:UINT64_MAX_ 18446744073709551615ULL
-// X86_64:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
-// X86_64:INT_LEAST64_MAX_ 9223372036854775807LL
-// X86_64:UINT_LEAST64_MAX_ 18446744073709551615ULL
-// X86_64:INT_FAST64_MIN_ (-9223372036854775807LL -1)
-// X86_64:INT_FAST64_MAX_ 9223372036854775807LL
-// X86_64:UINT_FAST64_MAX_ 18446744073709551615ULL
-//
-// X86_64:INTPTR_MIN_ (-9223372036854775807LL -1)
-// X86_64:INTPTR_MAX_ 9223372036854775807LL
-// X86_64:UINTPTR_MAX_ 18446744073709551615ULL
-// X86_64:PTRDIFF_MIN_ (-9223372036854775807LL -1)
-// X86_64:PTRDIFF_MAX_ 9223372036854775807LL
-// X86_64:SIZE_MAX_ 18446744073709551615ULL
+// X86_64:INT64_MAX_ 9223372036854775807L
+// X86_64:INT64_MIN_ (-9223372036854775807L -1)
+// X86_64:UINT64_MAX_ 18446744073709551615UL
+// X86_64:INT_LEAST64_MIN_ (-9223372036854775807L -1)
+// X86_64:INT_LEAST64_MAX_ 9223372036854775807L
+// X86_64:UINT_LEAST64_MAX_ 18446744073709551615UL
+// X86_64:INT_FAST64_MIN_ (-9223372036854775807L -1)
+// X86_64:INT_FAST64_MAX_ 9223372036854775807L
+// X86_64:UINT_FAST64_MAX_ 18446744073709551615UL
+//
+// X86_64:INTPTR_MIN_ (-9223372036854775807L -1)
+// X86_64:INTPTR_MAX_ 9223372036854775807L
+// X86_64:UINTPTR_MAX_ 18446744073709551615UL
+// X86_64:PTRDIFF_MIN_ (-9223372036854775807L -1)
+// X86_64:PTRDIFF_MAX_ 9223372036854775807L
+// X86_64:SIZE_MAX_ 18446744073709551615UL
//
// X86_64:INTMAX_MIN_ (-9223372036854775807L -1)
// X86_64:INTMAX_MAX_ 9223372036854775807L
@@ -1146,19 +1146,18 @@
// X86_64:WCHAR_MAX_ 2147483647
// X86_64:WCHAR_MIN_ (-2147483647 -1)
//
-// X86_64:INT8_C_(0) (0)
-// X86_64:UINT8_C_(0) (0U)
-// X86_64:INT16_C_(0) (0)
-// X86_64:UINT16_C_(0) (0U)
-// X86_64:INT32_C_(0) (0)
-// X86_64:UINT32_C_(0) (0U)
-// X86_64:INT64_C_(0) (0LL)
-// X86_64:UINT64_C_(0) (0ULL)
+// X86_64:INT8_C_(0) 0
+// X86_64:UINT8_C_(0) 0U
+// X86_64:INT16_C_(0) 0
+// X86_64:UINT16_C_(0) 0U
+// X86_64:INT32_C_(0) 0
+// X86_64:UINT32_C_(0) 0U
+// X86_64:INT64_C_(0) 0L
+// X86_64:UINT64_C_(0) 0UL
//
-// X86_64:INTMAX_C_(0) (0LL)
-// X86_64:UINTMAX_C_(0) (0ULL)
+// X86_64:INTMAX_C_(0) 0LL
+// X86_64:UINTMAX_C_(0) 0ULL
//
-// RUN: true
#include <stdint.h>
diff --git a/test/Preprocessor/x86_target_features.c b/test/Preprocessor/x86_target_features.c
index 90a717b81e8a..f8574e25d474 100644
--- a/test/Preprocessor/x86_target_features.c
+++ b/test/Preprocessor/x86_target_features.c
@@ -1,35 +1,34 @@
// FIXME: Use -triple, not -ccc-host-triple.
-// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -x c -E -dM -o %t %s &&
-// RUN: grep '#define __SSE2_MATH__ 1' %t &&
-// RUN: grep '#define __SSE2__ 1' %t &&
-// RUN: grep '#define __SSE3__ 1' %t &&
-// RUN: grep '#define __SSE4_1__ 1' %t &&
-// RUN: grep '#define __SSE4_2__ 1' %t &&
-// RUN: grep '#define __SSE_MATH__ 1' %t &&
-// RUN: grep '#define __SSE__ 1' %t &&
-// RUN: grep '#define __SSSE3__ 1' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -x c -E -dM -o %t %s
+// RUN: grep '#define __SSE2_MATH__ 1' %t
+// RUN: grep '#define __SSE2__ 1' %t
+// RUN: grep '#define __SSE3__ 1' %t
+// RUN: grep '#define __SSE4_1__ 1' %t
+// RUN: grep '#define __SSE4_2__ 1' %t
+// RUN: grep '#define __SSE_MATH__ 1' %t
+// RUN: grep '#define __SSE__ 1' %t
+// RUN: grep '#define __SSSE3__ 1' %t
-// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -mno-sse2 -x c -E -dM -o %t %s &&
-// RUN: grep '#define __SSE2_MATH__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE2__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE3__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE4_1__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE4_2__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE_MATH__ 1' %t &&
-// RUN: grep '#define __SSE__ 1' %t &&
-// RUN: grep '#define __SSSE3__ 1' %t | count 0 &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -mno-sse2 -x c -E -dM -o %t %s
+// RUN: grep '#define __SSE2_MATH__ 1' %t | count 0
+// RUN: grep '#define __SSE2__ 1' %t | count 0
+// RUN: grep '#define __SSE3__ 1' %t | count 0
+// RUN: grep '#define __SSE4_1__ 1' %t | count 0
+// RUN: grep '#define __SSE4_2__ 1' %t | count 0
+// RUN: grep '#define __SSE_MATH__ 1' %t
+// RUN: grep '#define __SSE__ 1' %t
+// RUN: grep '#define __SSSE3__ 1' %t | count 0
-// RUN: clang -ccc-host-triple i386-unknown-unknown -march=pentium-m -x c -E -dM -o %t %s &&
-// RUN: grep '#define __SSE2_MATH__ 1' %t &&
-// RUN: grep '#define __SSE2__ 1' %t &&
-// RUN: grep '#define __SSE3__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE4_1__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE4_2__ 1' %t | count 0 &&
-// RUN: grep '#define __SSE_MATH__ 1' %t &&
-// RUN: grep '#define __SSE__ 1' %t &&
-// RUN: grep '#define __SSSE3__ 1' %t | count 0 &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -march=pentium-m -x c -E -dM -o %t %s
+// RUN: grep '#define __SSE2_MATH__ 1' %t
+// RUN: grep '#define __SSE2__ 1' %t
+// RUN: grep '#define __SSE3__ 1' %t | count 0
+// RUN: grep '#define __SSE4_1__ 1' %t | count 0
+// RUN: grep '#define __SSE4_2__ 1' %t | count 0
+// RUN: grep '#define __SSE_MATH__ 1' %t
+// RUN: grep '#define __SSE__ 1' %t
+// RUN: grep '#define __SSSE3__ 1' %t | count 0
-// RUN: true
diff --git a/test/Rewriter/objc-ivar-receiver-1.m b/test/Rewriter/objc-ivar-receiver-1.m
index c7ad05a1884d..3898f715b71f 100644
--- a/test/Rewriter/objc-ivar-receiver-1.m
+++ b/test/Rewriter/objc-ivar-receiver-1.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -rewrite-objc %s -o - &&
+// RUN: clang-cc -rewrite-objc %s -o -
// RUN: clang-cc -rewrite-objc %s -o - | grep 'newInv->_container'
@interface NSMutableArray
diff --git a/test/Sema/128bitint.c b/test/Sema/128bitint.c
index 2a18d904f8f2..a068d81e4981 100644
--- a/test/Sema/128bitint.c
+++ b/test/Sema/128bitint.c
@@ -1,6 +1,9 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify -triple x86_64-apple-darwin9 %s
typedef int i128 __attribute__((__mode__(TI)));
typedef unsigned u128 __attribute__((__mode__(TI)));
int a[((i128)-1 ^ (i128)-2) == 1 ? 1 : -1];
int a[(u128)-1 > 1LL ? 1 : -1];
+
+// PR5435
+__uint128_t b = (__uint128_t)-1;
diff --git a/test/Sema/PR2727.c b/test/Sema/PR2727.c
index 52d8392ee9e5..0829dc239df8 100644
--- a/test/Sema/PR2727.c
+++ b/test/Sema/PR2727.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -verify -fsyntax-only -std=c90 %s &&
+// RUN: clang-cc -verify -fsyntax-only -std=c90 %s
// RUN: clang-cc -verify -fsyntax-only -std=c99 %s
int f (int x)
diff --git a/test/Sema/PR2728.c b/test/Sema/PR2728.c
index 26c96fe625be..e8c2e268b5d7 100644
--- a/test/Sema/PR2728.c
+++ b/test/Sema/PR2728.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -verify -fsyntax-only -std=c90 %s &&
+// RUN: clang-cc -verify -fsyntax-only -std=c90 %s
// RUN: clang-cc -verify -fsyntax-only -std=c99 %s
struct s
diff --git a/test/Sema/attr-format_arg.c b/test/Sema/attr-format_arg.c
index 0830951acc89..5f06f4ba3fc9 100644
--- a/test/Sema/attr-format_arg.c
+++ b/test/Sema/attr-format_arg.c
@@ -1,6 +1,6 @@
// RUN: clang-cc -fsyntax-only -verify %s
-#include <stdio.h>
+int printf(const char *, ...);
const char* f(const char *s) __attribute__((format_arg(1)));
diff --git a/test/Sema/attr-malloc.c b/test/Sema/attr-malloc.c
index 1adcf074a499..6483ffc4c1a6 100644
--- a/test/Sema/attr-malloc.c
+++ b/test/Sema/attr-malloc.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -verify -fsyntax-only %s &&
-// RUN: clang-cc -emit-llvm -o %t %s &&
+// RUN: clang -Xclang -verify -fsyntax-only %s
+// RUN: clang -emit-llvm -S -o %t %s
#include <stdlib.h>
@@ -16,7 +16,7 @@ __attribute((malloc)) int (*g)(); // expected-warning{{'malloc' attribute only a
__attribute((malloc))
void * xalloc(unsigned n) { return malloc(n); } // no-warning
-// RUN: grep 'define noalias .* @xalloc(' %t &&
+// RUN: grep 'define noalias .* @xalloc(' %t
#define malloc_like __attribute((__malloc__))
void * xalloc2(unsigned) malloc_like;
diff --git a/test/Sema/block-byref-args.c b/test/Sema/block-byref-args.c
index 39745d54efa4..06bab121f917 100644
--- a/test/Sema/block-byref-args.c
+++ b/test/Sema/block-byref-args.c
@@ -1,6 +1,6 @@
// RUN: clang-cc %s -fsyntax-only -verify -fblocks
-#include <stdio.h>
+int printf(const char *, ...);
int main(int argc, char **argv) {
__block void(*bobTheFunction)(void);
diff --git a/test/Sema/block-storageclass.c b/test/Sema/block-storageclass.c
index 3d2527b3f4e8..aacf8be2c06d 100644
--- a/test/Sema/block-storageclass.c
+++ b/test/Sema/block-storageclass.c
@@ -1,6 +1,6 @@
// RUN: clang-cc %s -fsyntax-only -verify -fblocks
-#include <stdio.h>
+int printf(const char *, ...);
void _Block_byref_release(void*src){}
int main() {
diff --git a/test/Sema/builtin-object-size.c b/test/Sema/builtin-object-size.c
index 4b15cb1f0e23..0c6d288d8c18 100644
--- a/test/Sema/builtin-object-size.c
+++ b/test/Sema/builtin-object-size.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s &&
+// RUN: clang-cc -fsyntax-only -verify %s
// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin9 -verify %s
int a[10];
diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c
index 102115b3bf2b..f65aab463f57 100644
--- a/test/Sema/callingconv.c
+++ b/test/Sema/callingconv.c
@@ -17,3 +17,7 @@ void __attribute__((fastcall)) test1(void) {
void __attribute__((fastcall)) test2(int a, ...) { // expected-error {{variadic function cannot use 'fastcall' calling convention}}
}
+
+void __attribute__((cdecl)) ctest0() {}
+
+void __attribute__((cdecl(1))) ctest1(float x) {} // expected-error {{attribute requires 0 argument(s)}}
diff --git a/test/Sema/check-increment.c b/test/Sema/check-increment.c
index 9809544854d8..72eae06bfa1b 100644
--- a/test/Sema/check-increment.c
+++ b/test/Sema/check-increment.c
@@ -1,6 +1,6 @@
// RUN: clang-cc -fsyntax-only -verify %s
-#include <stdio.h>
+int printf(const char *, ...);
typedef int *pint;
int main() {
int a[5] = {0};
diff --git a/test/Sema/compare.c b/test/Sema/compare.c
index 9cbbfba935bd..01a216ffec22 100644
--- a/test/Sema/compare.c
+++ b/test/Sema/compare.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+// RUN: clang-cc -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare %s
int test(char *C) { // nothing here should warn.
return C != ((void*)0);
@@ -8,23 +8,194 @@ int test(char *C) { // nothing here should warn.
}
int ints(long a, unsigned long b) {
- return (a == b) + // expected-warning {{comparison of integers of different signs}}
- ((int)a == b) + // expected-warning {{comparison of integers of different signs}}
- ((short)a == b) + // expected-warning {{comparison of integers of different signs}}
- (a == (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
- (a == (unsigned short) b); // expected-warning {{comparison of integers of different signs}}
-
- enum Enum {B};
- return (a == B) +
- ((int)a == B) +
- ((short)a == B) +
- (a == (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
- (a == (unsigned short) B); // expected-warning {{comparison of integers of different signs}}
-
- // Should be able to prove all of these are non-negative.
- return (b == (long) B) +
- (b == (int) B) +
- (b == (short) B);
+ enum EnumA {A};
+ enum EnumB {B};
+ enum EnumC {C = 0x10000};
+ return
+ // (a,b)
+ (a == (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ (a == (unsigned int) b) +
+ (a == (unsigned short) b) +
+ (a == (unsigned char) b) +
+ ((long) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((long) a == (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a == (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a == (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a == (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) b) +
+ (a < (unsigned short) b) +
+ (a < (unsigned char) b) +
+ ((long) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((long) a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+
+ // (A,b)
+ (A == (unsigned long) b) +
+ (A == (unsigned int) b) +
+ (A == (unsigned short) b) +
+ (A == (unsigned char) b) +
+ ((long) A == b) +
+ ((int) A == b) +
+ ((short) A == b) +
+ ((signed char) A == b) +
+ ((long) A == (unsigned long) b) +
+ ((int) A == (unsigned int) b) +
+ ((short) A == (unsigned short) b) +
+ ((signed char) A == (unsigned char) b) +
+ (A < (unsigned long) b) +
+ (A < (unsigned int) b) +
+ (A < (unsigned short) b) +
+ (A < (unsigned char) b) +
+ ((long) A < b) +
+ ((int) A < b) +
+ ((short) A < b) +
+ ((signed char) A < b) +
+ ((long) A < (unsigned long) b) +
+ ((int) A < (unsigned int) b) +
+ ((short) A < (unsigned short) b) +
+ ((signed char) A < (unsigned char) b) +
+
+ // (a,B)
+ (a == (unsigned long) B) +
+ (a == (unsigned int) B) +
+ (a == (unsigned short) B) +
+ (a == (unsigned char) B) +
+ ((long) a == B) +
+ ((int) a == B) +
+ ((short) a == B) +
+ ((signed char) a == B) +
+ ((long) a == (unsigned long) B) +
+ ((int) a == (unsigned int) B) +
+ ((short) a == (unsigned short) B) +
+ ((signed char) a == (unsigned char) B) +
+ (a < (unsigned long) B) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) B) +
+ (a < (unsigned short) B) +
+ (a < (unsigned char) B) +
+ ((long) a < B) +
+ ((int) a < B) +
+ ((short) a < B) +
+ ((signed char) a < B) +
+ ((long) a < (unsigned long) B) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) B) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) B) + // expected-warning {{comparison of integers of different signs}}
+
+ // (C,b)
+ (C == (unsigned long) b) +
+ (C == (unsigned int) b) +
+ (C == (unsigned short) b) +
+ (C == (unsigned char) b) +
+ ((long) C == b) +
+ ((int) C == b) +
+ ((short) C == b) +
+ ((signed char) C == b) +
+ ((long) C == (unsigned long) b) +
+ ((int) C == (unsigned int) b) +
+ ((short) C == (unsigned short) b) +
+ ((signed char) C == (unsigned char) b) +
+ (C < (unsigned long) b) +
+ (C < (unsigned int) b) +
+ (C < (unsigned short) b) +
+ (C < (unsigned char) b) +
+ ((long) C < b) +
+ ((int) C < b) +
+ ((short) C < b) +
+ ((signed char) C < b) +
+ ((long) C < (unsigned long) b) +
+ ((int) C < (unsigned int) b) +
+ ((short) C < (unsigned short) b) +
+ ((signed char) C < (unsigned char) b) +
+
+ // (a,C)
+ (a == (unsigned long) C) +
+ (a == (unsigned int) C) +
+ (a == (unsigned short) C) +
+ (a == (unsigned char) C) +
+ ((long) a == C) +
+ ((int) a == C) +
+ ((short) a == C) +
+ ((signed char) a == C) +
+ ((long) a == (unsigned long) C) +
+ ((int) a == (unsigned int) C) +
+ ((short) a == (unsigned short) C) +
+ ((signed char) a == (unsigned char) C) +
+ (a < (unsigned long) C) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) C) +
+ (a < (unsigned short) C) +
+ (a < (unsigned char) C) +
+ ((long) a < C) +
+ ((int) a < C) +
+ ((short) a < C) +
+ ((signed char) a < C) +
+ ((long) a < (unsigned long) C) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) C) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) C) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) C) + // expected-warning {{comparison of integers of different signs}}
+
+ // (0x80000,b)
+ (0x80000 == (unsigned long) b) +
+ (0x80000 == (unsigned int) b) +
+ (0x80000 == (unsigned short) b) +
+ (0x80000 == (unsigned char) b) +
+ ((long) 0x80000 == b) +
+ ((int) 0x80000 == b) +
+ ((short) 0x80000 == b) +
+ ((signed char) 0x80000 == b) +
+ ((long) 0x80000 == (unsigned long) b) +
+ ((int) 0x80000 == (unsigned int) b) +
+ ((short) 0x80000 == (unsigned short) b) +
+ ((signed char) 0x80000 == (unsigned char) b) +
+ (0x80000 < (unsigned long) b) +
+ (0x80000 < (unsigned int) b) +
+ (0x80000 < (unsigned short) b) +
+ (0x80000 < (unsigned char) b) +
+ ((long) 0x80000 < b) +
+ ((int) 0x80000 < b) +
+ ((short) 0x80000 < b) +
+ ((signed char) 0x80000 < b) +
+ ((long) 0x80000 < (unsigned long) b) +
+ ((int) 0x80000 < (unsigned int) b) +
+ ((short) 0x80000 < (unsigned short) b) +
+ ((signed char) 0x80000 < (unsigned char) b) +
+
+ // (a,0x80000)
+ (a == (unsigned long) 0x80000) +
+ (a == (unsigned int) 0x80000) +
+ (a == (unsigned short) 0x80000) +
+ (a == (unsigned char) 0x80000) +
+ ((long) a == 0x80000) +
+ ((int) a == 0x80000) +
+ ((short) a == 0x80000) +
+ ((signed char) a == 0x80000) +
+ ((long) a == (unsigned long) 0x80000) +
+ ((int) a == (unsigned int) 0x80000) +
+ ((short) a == (unsigned short) 0x80000) +
+ ((signed char) a == (unsigned char) 0x80000) +
+ (a < (unsigned long) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) 0x80000) +
+ (a < (unsigned short) 0x80000) +
+ (a < (unsigned char) 0x80000) +
+ ((long) a < 0x80000) +
+ ((int) a < 0x80000) +
+ ((short) a < 0x80000) +
+ ((signed char) a < 0x80000) +
+ ((long) a < (unsigned long) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+
+ 10
+ ;
}
int equal(char *a, const char *b) {
diff --git a/test/Sema/conditional-expr.c b/test/Sema/conditional-expr.c
index 3bfeae5d4c5e..8cac32c82f45 100644
--- a/test/Sema/conditional-expr.c
+++ b/test/Sema/conditional-expr.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify -pedantic %s
+// RUN: clang-cc -fsyntax-only -verify -pedantic -Wsign-compare %s
void foo() {
*(0 ? (double *)0 : (void *)0) = 0;
// FIXME: GCC doesn't consider the the following two statements to be errors.
diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c
index 72db14c82053..39a24b326991 100644
--- a/test/Sema/const-eval.c
+++ b/test/Sema/const-eval.c
@@ -68,3 +68,10 @@ EVAL_EXPR(32, (int*)0 != (int*)0 ? -1 : 1)
EVAL_EXPR(33, (void*)0 - (void*)0 == 0 ? 1 : -1)
void foo(void) {}
EVAL_EXPR(34, (foo == (void *)0) ? -1 : 1)
+
+// No PR. Mismatched bitwidths lead to a crash on second evaluation.
+const _Bool constbool = 0;
+EVAL_EXPR(35, constbool)
+EVAL_EXPR(36, constbool)
+
+EVAL_EXPR(37, (1,2.0) == 2.0)
diff --git a/test/Sema/conversion-64-32.c b/test/Sema/conversion-64-32.c
new file mode 100644
index 000000000000..53830fd061c4
--- /dev/null
+++ b/test/Sema/conversion-64-32.c
@@ -0,0 +1,5 @@
+// RUN: clang-cc -fsyntax-only -verify -Wshorten-64-to-32 -triple x86_64-apple-darwin %s
+
+int test0(long v) {
+ return v; // expected-warning {{implicit cast loses integer precision}}
+}
diff --git a/test/Sema/conversion.c b/test/Sema/conversion.c
new file mode 100644
index 000000000000..bca23f8f8df8
--- /dev/null
+++ b/test/Sema/conversion.c
@@ -0,0 +1,237 @@
+// RUN: clang-cc -fsyntax-only -verify -Wconversion -triple x86_64-apple-darwin %s
+
+#define BIG 0x7f7f7f7f7f7f7f7fL
+
+void test0(char c, short s, int i, long l, long long ll) {
+ c = c;
+ c = s; // expected-warning {{implicit cast loses integer precision}}
+ c = i; // expected-warning {{implicit cast loses integer precision}}
+ c = l; // expected-warning {{implicit cast loses integer precision}}
+ s = c;
+ s = s;
+ s = i; // expected-warning {{implicit cast loses integer precision}}
+ s = l; // expected-warning {{implicit cast loses integer precision}}
+ i = c;
+ i = s;
+ i = i;
+ i = l; // expected-warning {{implicit cast loses integer precision}}
+ l = c;
+ l = s;
+ l = i;
+ l = l;
+
+ c = (char) 0;
+ c = (short) 0;
+ c = (int) 0;
+ c = (long) 0;
+ s = (char) 0;
+ s = (short) 0;
+ s = (int) 0;
+ s = (long) 0;
+ i = (char) 0;
+ i = (short) 0;
+ i = (int) 0;
+ i = (long) 0;
+ l = (char) 0;
+ l = (short) 0;
+ l = (int) 0;
+ l = (long) 0;
+
+ c = (char) BIG;
+ c = (short) BIG; // expected-warning {{implicit cast loses integer precision}}
+ c = (int) BIG; // expected-warning {{implicit cast loses integer precision}}
+ c = (long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ s = (char) BIG;
+ s = (short) BIG;
+ s = (int) BIG; // expected-warning {{implicit cast loses integer precision}}
+ s = (long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ i = (char) BIG;
+ i = (short) BIG;
+ i = (int) BIG;
+ i = (long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ l = (char) BIG;
+ l = (short) BIG;
+ l = (int) BIG;
+ l = (long) BIG;
+}
+
+char test1(long long ll) {
+ return (long long) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (long) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (int) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (short) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (char) ll;
+ return (long long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (int) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (short) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (char) BIG;
+}
+
+short test2(long long ll) {
+ return (long long) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (long) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (int) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (short) ll;
+ return (char) ll;
+ return (long long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (int) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (short) BIG;
+ return (char) BIG;
+}
+
+int test3(long long ll) {
+ return (long long) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (long) ll; // expected-warning {{implicit cast loses integer precision}}
+ return (int) ll;
+ return (short) ll;
+ return (char) ll;
+ return (long long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (long) BIG; // expected-warning {{implicit cast loses integer precision}}
+ return (int) BIG;
+ return (short) BIG;
+ return (char) BIG;
+}
+
+long test4(long long ll) {
+ return (long long) ll;
+ return (long) ll;
+ return (int) ll;
+ return (short) ll;
+ return (char) ll;
+ return (long long) BIG;
+ return (long) BIG;
+ return (int) BIG;
+ return (short) BIG;
+ return (char) BIG;
+}
+
+long long test5(long long ll) {
+ return (long long) ll;
+ return (long) ll;
+ return (int) ll;
+ return (short) ll;
+ return (char) ll;
+ return (long long) BIG;
+ return (long) BIG;
+ return (int) BIG;
+ return (short) BIG;
+ return (char) BIG;
+}
+
+void takes_char(char);
+void takes_short(short);
+void takes_int(int);
+void takes_long(long);
+void takes_longlong(long long);
+void takes_float(float);
+void takes_double(double);
+void takes_longdouble(long double);
+
+void test6(char v) {
+ takes_char(v);
+ takes_short(v);
+ takes_int(v);
+ takes_long(v);
+ takes_longlong(v);
+ takes_float(v);
+ takes_double(v);
+ takes_longdouble(v);
+}
+
+void test7(short v) {
+ takes_char(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_short(v);
+ takes_int(v);
+ takes_long(v);
+ takes_longlong(v);
+ takes_float(v);
+ takes_double(v);
+ takes_longdouble(v);
+}
+
+void test8(int v) {
+ takes_char(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_short(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_int(v);
+ takes_long(v);
+ takes_longlong(v);
+ takes_float(v);
+ takes_double(v);
+ takes_longdouble(v);
+}
+
+void test9(long v) {
+ takes_char(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_short(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_int(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_long(v);
+ takes_longlong(v);
+ takes_float(v);
+ takes_double(v);
+ takes_longdouble(v);
+}
+
+void test10(long long v) {
+ takes_char(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_short(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_int(v); // expected-warning {{implicit cast loses integer precision}}
+ takes_long(v);
+ takes_longlong(v);
+ takes_float(v);
+ takes_double(v);
+ takes_longdouble(v);
+}
+
+void test11(float v) {
+ takes_char(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_short(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_int(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_long(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_longlong(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_float(v);
+ takes_double(v);
+ takes_longdouble(v);
+}
+
+void test12(double v) {
+ takes_char(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_short(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_int(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_long(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_longlong(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_float(v); // expected-warning {{implicit cast loses floating-point precision}}
+ takes_double(v);
+ takes_longdouble(v);
+}
+
+void test13(long double v) {
+ takes_char(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_short(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_int(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_long(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_longlong(v); // expected-warning {{implicit cast turns floating-point number into integer}}
+ takes_float(v); // expected-warning {{implicit cast loses floating-point precision}}
+ takes_double(v); // expected-warning {{implicit cast loses floating-point precision}}
+ takes_longdouble(v);
+}
+
+void test14(long l) {
+ // Fine because of the boolean whitelist.
+ char c;
+ c = (l == 4);
+ c = ((l <= 4) && (l >= 0));
+ c = ((l <= 4) && (l >= 0)) || (l > 20);
+}
+
+void test15(char c) {
+ c = c + 1 + c * 2;
+ c = (short) c + 1 + c * 2; // expected-warning {{implicit cast loses integer precision}}
+}
+
+// PR 5422
+extern void *test16_external;
+void test16(void) {
+ int a = (unsigned long) &test16_external; // expected-warning {{implicit cast loses integer precision}}
+}
diff --git a/test/Sema/expr-comma-c89.c b/test/Sema/expr-comma-c89.c
index b2b17dc33591..ffe8b696f608 100644
--- a/test/Sema/expr-comma-c89.c
+++ b/test/Sema/expr-comma-c89.c
@@ -1,7 +1,6 @@
// RUN: clang-cc %s -fsyntax-only -verify -std=c99
// rdar://6095180
-#include <assert.h>
struct s { char c[17]; };
extern struct s foo(void);
diff --git a/test/Sema/expr-comma.c b/test/Sema/expr-comma.c
index 64079866ca99..3a05130eae32 100644
--- a/test/Sema/expr-comma.c
+++ b/test/Sema/expr-comma.c
@@ -1,7 +1,6 @@
// RUN: clang-cc %s -fsyntax-only -verify -std=c89
// rdar://6095180
-#include <assert.h>
struct s { char c[17]; };
extern struct s foo(void);
diff --git a/test/Sema/format-attr-pr4470.c b/test/Sema/format-attr-pr4470.c
index c03c573b7274..24eece8878e2 100644
--- a/test/Sema/format-attr-pr4470.c
+++ b/test/Sema/format-attr-pr4470.c
@@ -1,7 +1,7 @@
// RUN: clang-cc -fsyntax-only -verify -Wformat=2 %s
-#include <stdio.h>
#include <stdarg.h>
+int vprintf(const char *, va_list);
const char *foo(const char *format) __attribute__((format_arg(1)));
diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c
index 797e53c1bd22..0a9fccebd7fd 100644
--- a/test/Sema/format-strings.c
+++ b/test/Sema/format-strings.c
@@ -1,17 +1,20 @@
// RUN: clang-cc -fsyntax-only -verify -Wformat-nonliteral %s
-// Define this to get vasprintf on Linux
-#define _GNU_SOURCE
-
-#include <stdio.h>
#include <stdarg.h>
+typedef __typeof(sizeof(int)) size_t;
+typedef struct _FILE FILE;
+int fprintf(FILE *, const char *restrict, ...);
+int printf(const char *restrict, ...);
+int snprintf(char *restrict, size_t, const char *restrict, ...);
+int sprintf(char *restrict, const char *restrict, ...);
+int vasprintf(char **, const char *, va_list);
+int vfprintf(FILE *, const char *restrict, va_list);
+int vprintf(const char *restrict, va_list);
+int vsnprintf(char *, size_t, const char *, va_list);
+int vsprintf(char *restrict, const char *restrict, va_list);
char * global_fmt;
-#if defined(_WIN32) || defined(_WIN64)
-extern int snprintf(char*, size_t, const char*, ...);
-#endif
-
void check_string_literal( FILE* fp, const char* s, char *buf, ... ) {
char * b;
diff --git a/test/Sema/i-c-e.c b/test/Sema/i-c-e.c
index de279669922b..6e14833166d8 100644
--- a/test/Sema/i-c-e.c
+++ b/test/Sema/i-c-e.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -fsyntax-only -verify -pedantic -fpascal-strings
+// RUN: clang %s -fsyntax-only -Xclang -verify -pedantic -fpascal-strings
#include <stdint.h>
#include <limits.h>
diff --git a/test/Sema/implicit-builtin-redecl.c b/test/Sema/implicit-builtin-redecl.c
index 36513bafb050..fc51312f1770 100644
--- a/test/Sema/implicit-builtin-redecl.c
+++ b/test/Sema/implicit-builtin-redecl.c
@@ -23,4 +23,4 @@ int f3() {
return index << 2;
}
-typedef int rindex; \ No newline at end of file
+typedef int rindex;
diff --git a/test/Sema/implicit-def.c b/test/Sema/implicit-def.c
index 2c2594680a11..3b31b999667c 100644
--- a/test/Sema/implicit-def.c
+++ b/test/Sema/implicit-def.c
@@ -1,4 +1,4 @@
-/* RUN: clang-cc -fsyntax-only %s -std=c89 &&
+/* RUN: clang-cc -fsyntax-only %s -std=c89
* RUN: not clang-cc -fsyntax-only %s -std=c99 -pedantic-errors
*/
diff --git a/test/Sema/parentheses.c b/test/Sema/parentheses.c
index a8ad260bf8b5..f9f647c9cff7 100644
--- a/test/Sema/parentheses.c
+++ b/test/Sema/parentheses.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -Wparentheses -fsyntax-only -verify %s &&
+// RUN: clang-cc -Wparentheses -fsyntax-only -verify %s
// RUN: clang-cc -Wparentheses -fixit %s -o - | clang-cc -Wparentheses -Werror -
// Test the various warnings under -Wparentheses
diff --git a/test/Sema/pointer-conversion.c b/test/Sema/pointer-conversion.c
new file mode 100644
index 000000000000..5f41ff67411b
--- /dev/null
+++ b/test/Sema/pointer-conversion.c
@@ -0,0 +1,10 @@
+//RUN: clang-cc -fsyntax-only -verify %s
+
+char * c;
+char const ** c2 = &c; // expected-warning {{initializing, 'char const **' and 'char **' have different qualifiers in nested pointer types}}
+
+typedef char dchar;
+dchar *** c3 = &c2; // expected-warning {{initializing, 'dchar ***' and 'char const ***' have different qualifiers in nested pointer types}}
+
+volatile char * c4;
+char ** c5 = &c4; // expected-warning {{initializing, 'char **' and 'char volatile **' have different qualifiers in nested pointer types}}
diff --git a/test/Sema/pragma-pack-4.c b/test/Sema/pragma-pack-4.c
index f6f107da742b..3ccaf7e96ce6 100644
--- a/test/Sema/pragma-pack-4.c
+++ b/test/Sema/pragma-pack-4.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i686-apple-darwin9 %s -fsyntax-only -verify &&
+// RUN: clang-cc -triple i686-apple-darwin9 %s -fsyntax-only -verify
// RUN: clang-cc -triple x86_64-apple-darwin9 %s -fsyntax-only -verify
// rdar://problem/7095436
diff --git a/test/Sema/return.c b/test/Sema/return.c
index cdd31059b3e7..ad75cf1a0b6d 100644
--- a/test/Sema/return.c
+++ b/test/Sema/return.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -fsyntax-only -verify -fblocks
+// RUN: clang %s -fsyntax-only -Xclang -verify -fblocks
// clang emits the following warning by default.
// With GCC, -pedantic, -Wreturn-type or -Wall are required to produce the
diff --git a/test/Sema/shift.c b/test/Sema/shift.c
index 2516d1b86107..fdfebc589a77 100644
--- a/test/Sema/shift.c
+++ b/test/Sema/shift.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -Wall -fsyntax-only -verify %s
+// RUN: clang -Wall -fsyntax-only -Xclang -verify %s
#include <limits.h>
diff --git a/test/Sema/ucn-cstring.c b/test/Sema/ucn-cstring.c
index 6d021fd82d16..fb9a3b604eb7 100644
--- a/test/Sema/ucn-cstring.c
+++ b/test/Sema/ucn-cstring.c
@@ -1,6 +1,6 @@
// RUN: clang-cc %s -verify -fsyntax-only -pedantic
-#include <stdio.h>
+int printf(const char *, ...);
int main(void) {
int a[sizeof("hello \u2192 \u2603 \u2190 world") == 24 ? 1 : -1];
diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c
index 8d2f0b1fa83e..e928997dd8ba 100644
--- a/test/Sema/varargs.c
+++ b/test/Sema/varargs.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s &&
+// RUN: clang-cc -fsyntax-only -verify %s
// RUN: clang-cc -fsyntax-only -verify %s -triple x86_64-apple-darwin9
void f1(int a)
diff --git a/test/Sema/wchar.c b/test/Sema/wchar.c
index 16376009ab13..e201c7e49144 100644
--- a/test/Sema/wchar.c
+++ b/test/Sema/wchar.c
@@ -1,12 +1,20 @@
-// RUN: clang-cc %s -fsyntax-only -verify
-#include <wchar.h>
+// RUN: clang %s -fsyntax-only -Xclang -verify
+// RUN: clang %s -fsyntax-only -fshort-wchar -Xclang -verify -DSHORT_WCHAR
-int check_wchar_size[sizeof(*L"") == sizeof(wchar_t) ? 1 : -1];
+typedef __WCHAR_TYPE__ wchar_t;
+#if defined(_WIN32) || defined(_M_IX86) || defined(__CYGWIN__) \
+ || defined(_M_X64) || defined(SHORT_WCHAR)
+ #define WCHAR_T_TYPE unsigned short
+#else
+ #define WCHAR_T_TYPE int
+#endif
+
+int check_wchar_size[sizeof(*L"") == sizeof(wchar_t) ? 1 : -1];
+
void foo() {
- int t1[] = L"x";
+ WCHAR_T_TYPE t1[] = L"x";
wchar_t tab[] = L"x";
-
- int t2[] = "x"; // expected-error {{initialization}}
+ WCHAR_T_TYPE t2[] = "x"; // expected-error {{initialization}}
char t3[] = L"x"; // expected-error {{initialization}}
}
diff --git a/test/Sema/x86-intrinsics-headers.c b/test/Sema/x86-intrinsics-headers.c
index dd7dd5caf017..5b43e2bd07a4 100644
--- a/test/Sema/x86-intrinsics-headers.c
+++ b/test/Sema/x86-intrinsics-headers.c
@@ -1,5 +1,5 @@
-// RUN: clang -fsyntax-only %s &&
-// RUN: clang -fsyntax-only -fno-lax-vector-conversions %s &&
+// RUN: clang -fsyntax-only %s
+// RUN: clang -fsyntax-only -fno-lax-vector-conversions %s
// RUN: clang -fsyntax-only -x c++ %s
#if defined(i386) || defined(__x86_64__)
diff --git a/test/SemaCXX/__null.cpp b/test/SemaCXX/__null.cpp
index 4672801fd7bb..cf7851444092 100644
--- a/test/SemaCXX/__null.cpp
+++ b/test/SemaCXX/__null.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify &&
+// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify
// RUN: clang-cc -triple i686-unknown-unknown %s -fsyntax-only -verify
void f() {
diff --git a/test/SemaCXX/arrow-operator.cpp b/test/SemaCXX/arrow-operator.cpp
index 9c46e96afc0b..08b3cd4cc716 100644
--- a/test/SemaCXX/arrow-operator.cpp
+++ b/test/SemaCXX/arrow-operator.cpp
@@ -16,7 +16,10 @@ struct C : A, B {
struct D : A { };
-void f(C &c, D& d) {
+struct E; // expected-note {{forward declaration of 'struct E'}}
+
+void f(C &c, D& d, E& e) {
c->f(); // expected-error{{use of overloaded operator '->' is ambiguous}}
d->f();
-} \ No newline at end of file
+ e->f(); // expected-error{{incomplete definition of type}}
+}
diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp
new file mode 100644
index 000000000000..9e9d1522f4f6
--- /dev/null
+++ b/test/SemaCXX/builtins.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc %s -fsyntax-only -verify
+typedef const struct __CFString * CFStringRef;
+#define CFSTR __builtin___CFStringMakeConstantString
+
+void f() {
+ (void)CFStringRef(CFSTR("Hello"));
+} \ No newline at end of file
diff --git a/test/SemaCXX/cast-conversion.cpp b/test/SemaCXX/cast-conversion.cpp
index cbc24aef28d5..3b6a9d6f8c49 100644
--- a/test/SemaCXX/cast-conversion.cpp
+++ b/test/SemaCXX/cast-conversion.cpp
@@ -19,3 +19,28 @@ int main () {
// expected-warning {{expression result unused}}
}
+template<class T>
+struct X0 {
+ X0(const T &);
+};
+
+template<class T>
+X0<T> make_X0(const T &Val) {
+ return X0<T>(Val);
+}
+
+void test_X0() {
+ const char array[2];
+ make_X0(array);
+}
+
+// PR5210 recovery
+class C {
+protected:
+ template <int> float* &f0(); // expected-note{{candidate}}
+ template <unsigned> float* &f0(); // expected-note{{candidate}}
+
+ void f1() {
+ static_cast<float*>(f0<0>()); // expected-error{{ambiguous}}
+ }
+};
diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp
index 806b078e8df6..e38b6b312f98 100644
--- a/test/SemaCXX/compare.cpp
+++ b/test/SemaCXX/compare.cpp
@@ -1,15 +1,195 @@
-// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+// Force x86-64 because some of our heuristics are actually based
+// on integer sizes.
+
+// RUN: clang-cc -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare %s
int test0(long a, unsigned long b) {
- enum Enum {B};
- return (a == B) + // expected-warning {{comparison of integers of different signs}}
- ((int)a == B) + // expected-warning {{comparison of integers of different signs}}
- ((short)a == B) + // expected-warning {{comparison of integers of different signs}}
- (a == (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
- (a == (unsigned short) B); // expected-warning {{comparison of integers of different signs}}
-
- // Should be able to prove all of these are non-negative.
- return (b == (long) B) +
- (b == (int) B) +
- (b == (short) B);
+ enum EnumA {A};
+ enum EnumB {B};
+ enum EnumC {C = 0x10000};
+ return
+ // (a,b)
+ (a == (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ (a == (unsigned int) b) +
+ (a == (unsigned short) b) +
+ (a == (unsigned char) b) +
+ ((long) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((long) a == (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a == (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a == (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a == (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) b) +
+ (a < (unsigned short) b) +
+ (a < (unsigned char) b) +
+ ((long) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < b) + // expected-warning {{comparison of integers of different signs}}
+ ((long) a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+
+ // (A,b)
+ (A == (unsigned long) b) +
+ (A == (unsigned int) b) +
+ (A == (unsigned short) b) +
+ (A == (unsigned char) b) +
+ ((long) A == b) +
+ ((int) A == b) +
+ ((short) A == b) +
+ ((signed char) A == b) +
+ ((long) A == (unsigned long) b) +
+ ((int) A == (unsigned int) b) +
+ ((short) A == (unsigned short) b) +
+ ((signed char) A == (unsigned char) b) +
+ (A < (unsigned long) b) +
+ (A < (unsigned int) b) +
+ (A < (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
+ (A < (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ ((long) A < b) +
+ ((int) A < b) +
+ ((short) A < b) +
+ ((signed char) A < b) +
+ ((long) A < (unsigned long) b) +
+ ((int) A < (unsigned int) b) +
+ ((short) A < (unsigned short) b) +
+ ((signed char) A < (unsigned char) b) +
+
+ // (a,B)
+ (a == (unsigned long) B) +
+ (a == (unsigned int) B) +
+ (a == (unsigned short) B) +
+ (a == (unsigned char) B) +
+ ((long) a == B) +
+ ((int) a == B) +
+ ((short) a == B) +
+ ((signed char) a == B) +
+ ((long) a == (unsigned long) B) +
+ ((int) a == (unsigned int) B) +
+ ((short) a == (unsigned short) B) +
+ ((signed char) a == (unsigned char) B) +
+ (a < (unsigned long) B) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) B) +
+ (a < (unsigned short) B) +
+ (a < (unsigned char) B) +
+ ((long) a < B) +
+ ((int) a < B) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < B) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < B) + // expected-warning {{comparison of integers of different signs}}
+ ((long) a < (unsigned long) B) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) B) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) B) + // expected-warning {{comparison of integers of different signs}}
+
+ // (C,b)
+ (C == (unsigned long) b) +
+ (C == (unsigned int) b) +
+ (C == (unsigned short) b) +
+ (C == (unsigned char) b) +
+ ((long) C == b) +
+ ((int) C == b) +
+ ((short) C == b) +
+ ((signed char) C == b) +
+ ((long) C == (unsigned long) b) +
+ ((int) C == (unsigned int) b) +
+ ((short) C == (unsigned short) b) +
+ ((signed char) C == (unsigned char) b) +
+ (C < (unsigned long) b) +
+ (C < (unsigned int) b) +
+ (C < (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
+ (C < (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ ((long) C < b) +
+ ((int) C < b) +
+ ((short) C < b) +
+ ((signed char) C < b) +
+ ((long) C < (unsigned long) b) +
+ ((int) C < (unsigned int) b) +
+ ((short) C < (unsigned short) b) +
+ ((signed char) C < (unsigned char) b) +
+
+ // (a,C)
+ (a == (unsigned long) C) +
+ (a == (unsigned int) C) +
+ (a == (unsigned short) C) +
+ (a == (unsigned char) C) +
+ ((long) a == C) +
+ ((int) a == C) +
+ ((short) a == C) +
+ ((signed char) a == C) +
+ ((long) a == (unsigned long) C) +
+ ((int) a == (unsigned int) C) +
+ ((short) a == (unsigned short) C) +
+ ((signed char) a == (unsigned char) C) +
+ (a < (unsigned long) C) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) C) +
+ (a < (unsigned short) C) +
+ (a < (unsigned char) C) +
+ ((long) a < C) +
+ ((int) a < C) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < C) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < C) + // expected-warning {{comparison of integers of different signs}}
+ ((long) a < (unsigned long) C) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) C) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) C) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) C) + // expected-warning {{comparison of integers of different signs}}
+
+ // (0x80000,b)
+ (0x80000 == (unsigned long) b) +
+ (0x80000 == (unsigned int) b) +
+ (0x80000 == (unsigned short) b) +
+ (0x80000 == (unsigned char) b) +
+ ((long) 0x80000 == b) +
+ ((int) 0x80000 == b) +
+ ((short) 0x80000 == b) +
+ ((signed char) 0x80000 == b) +
+ ((long) 0x80000 == (unsigned long) b) +
+ ((int) 0x80000 == (unsigned int) b) +
+ ((short) 0x80000 == (unsigned short) b) +
+ ((signed char) 0x80000 == (unsigned char) b) +
+ (0x80000 < (unsigned long) b) +
+ (0x80000 < (unsigned int) b) +
+ (0x80000 < (unsigned short) b) +
+ (0x80000 < (unsigned char) b) +
+ ((long) 0x80000 < b) +
+ ((int) 0x80000 < b) +
+ ((short) 0x80000 < b) +
+ ((signed char) 0x80000 < b) +
+ ((long) 0x80000 < (unsigned long) b) +
+ ((int) 0x80000 < (unsigned int) b) +
+ ((short) 0x80000 < (unsigned short) b) +
+ ((signed char) 0x80000 < (unsigned char) b) +
+
+ // (a,0x80000)
+ (a == (unsigned long) 0x80000) +
+ (a == (unsigned int) 0x80000) +
+ (a == (unsigned short) 0x80000) +
+ (a == (unsigned char) 0x80000) +
+ ((long) a == 0x80000) +
+ ((int) a == 0x80000) +
+ ((short) a == 0x80000) +
+ ((signed char) a == 0x80000) +
+ ((long) a == (unsigned long) 0x80000) +
+ ((int) a == (unsigned int) 0x80000) +
+ ((short) a == (unsigned short) 0x80000) +
+ ((signed char) a == (unsigned char) 0x80000) +
+ (a < (unsigned long) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ (a < (unsigned int) 0x80000) +
+ (a < (unsigned short) 0x80000) +
+ (a < (unsigned char) 0x80000) +
+ ((long) a < 0x80000) +
+ ((int) a < 0x80000) +
+ ((short) a < 0x80000) +
+ ((signed char) a < 0x80000) +
+ ((long) a < (unsigned long) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((int) a < (unsigned int) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((signed char) a < (unsigned char) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+
+ 10
+ ;
}
diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp
index ebc40c14b743..1eec525f4834 100644
--- a/test/SemaCXX/composite-pointer-type.cpp
+++ b/test/SemaCXX/composite-pointer-type.cpp
@@ -32,4 +32,14 @@ int ptrcmp1(void *a, int *b) {
}
int ptrcmp2(long *a, int *b) {
return a < b; // expected-error{{distinct}}
-} \ No newline at end of file
+}
+
+// PR5509 - Multi-level pointers
+int f2() {
+ typedef int *IntPtr;
+ typedef IntPtr *IntPtrPtr;
+ typedef IntPtr const *IntPtrConstPtr;
+ IntPtrConstPtr i = 0;
+ IntPtrPtr j = 0;
+ return i != j;
+}
diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp
index da2dd67d061d..f76472bf2f42 100644
--- a/test/SemaCXX/conditional-expr.cpp
+++ b/test/SemaCXX/conditional-expr.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify -faccess-control -std=c++0x %s
+// RUN: clang-cc -fsyntax-only -verify -faccess-control -std=c++0x -Wsign-compare %s
// C++ rules for ?: are a lot stricter than C rules, and have to take into
// account more conversion options.
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index 20cf35b293b6..43186013aaa6 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -99,7 +99,9 @@ struct Current : Derived {
// FIXME. This is bad message!
struct M { // expected-note {{candidate function}} \
- // expected-note {{candidate function}}
+ // expected-note {{candidate function}} \
+ // expected-note {{declared here}} \
+ // expected-note {{declared here}}
M(int i, int j); // expected-note {{candidate function}} \
// // expected-note {{candidate function}}
};
@@ -110,9 +112,10 @@ struct N : M {
M m1;
};
-struct P : M { // expected-error {{default constructor for 'struct M' is missing in initialization of base class}}
- P() { }
- M m; // expected-error {{default constructor for 'struct M' is missing in initialization of member}}
+struct P : M {
+ P() { } // expected-error {{base class 'struct M'}} \
+ // expected-error {{member 'm'}}
+ M m; // expected-note {{member is declared here}}
};
struct Q {
@@ -155,3 +158,18 @@ class CopyConstructorTest {
B(B), // expected-warning {{field is uninitialized when used here}}
C(rhs.C || C) { } // expected-warning {{field is uninitialized when used here}}
};
+
+// Make sure we aren't marking default constructors when we shouldn't be.
+template<typename T>
+struct NDC {
+ T &ref;
+
+ NDC() { }
+ NDC(T &ref) : ref(ref) { }
+};
+
+struct X0 : NDC<int> {
+ X0(int &ref) : NDC<int>(ref), ndc(ref) { }
+
+ NDC<int> ndc;
+};
diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp
index 6182678e3113..c0c318ed3368 100644
--- a/test/SemaCXX/conversion-function.cpp
+++ b/test/SemaCXX/conversion-function.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify %s
class X {
public:
operator bool();
@@ -93,3 +93,31 @@ void f(Yb& a) {
char ch = a; // OK. calls Yb::operator char();
}
+// Test conversion + copy construction.
+class AutoPtrRef { };
+
+class AutoPtr {
+ // FIXME: Using 'unavailable' since we do not have access control yet.
+ // FIXME: The error message isn't so good.
+ AutoPtr(AutoPtr &) __attribute__((unavailable));
+
+public:
+ AutoPtr();
+ AutoPtr(AutoPtrRef);
+
+ operator AutoPtrRef();
+};
+
+AutoPtr make_auto_ptr();
+
+AutoPtr test_auto_ptr(bool Cond) {
+ AutoPtr p1( make_auto_ptr() );
+
+ AutoPtr p;
+ if (Cond)
+ return p; // expected-error{{incompatible type returning}}
+
+ return AutoPtr();
+}
+
+
diff --git a/test/SemaCXX/decltype-this.cpp b/test/SemaCXX/decltype-this.cpp
index fc001063c510..c6bf299f3f3b 100644
--- a/test/SemaCXX/decltype-this.cpp
+++ b/test/SemaCXX/decltype-this.cpp
@@ -1,4 +1,5 @@
-// RUN: clang-cc -fsyntax-only -verify -std=c++0x %t
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+
template<typename T, typename U> struct is_same {
static const bool value = false;
};
diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp
index 6cbb978dbb99..6adcdca3e177 100644
--- a/test/SemaCXX/default-constructor-initializers.cpp
+++ b/test/SemaCXX/default-constructor-initializers.cpp
@@ -9,18 +9,18 @@ struct X2 : X1 { // expected-note {{'struct X2' declared here}} \
X2(int);
};
-struct X3 : public X2 {
+struct X3 : public X2 { // expected-error {{must explicitly initialize the base class 'struct X2'}}
};
-X3 x3; // expected-error {{cannot define the implicit default constructor for 'struct X3', because base class 'struct X2' does not have any default constructor}}
+X3 x3; // expected-note {{first required here}}
-struct X4 {
+struct X4 { // expected-error {{must explicitly initialize the member 'x2'}} \
+ // expected-error {{must explicitly initialize the reference member 'rx2'}}
X2 x2; // expected-note {{member is declared here}}
X2 & rx2; // expected-note {{declared at}}
};
-X4 x4; // expected-error {{cannot define the implicit default constructor for 'struct X4', because member's type 'struct X2' does not have any default constructor}} \
- // expected-error {{cannot define the implicit default constructor for 'struct X4', because reference member 'rx2' cannot be default-initialized}}
+X4 x4; // expected-note {{first required here}}
struct Y1 { // has no implicit default constructor
@@ -45,12 +45,12 @@ Y4 y4;
// More tests
-struct Z1 {
+struct Z1 { // expected-error {{must explicitly initialize the reference member 'z'}} \
+ // expected-error {{must explicitly initialize the const member 'c1'}}
int& z; // expected-note {{declared at}}
const int c1; // expected-note {{declared at}}
volatile int v1;
};
-Z1 z1; // expected-error {{cannot define the implicit default constructor for 'struct Z1', because reference member 'z' cannot be default-initialized}} \
- // expected-error {{cannot define the implicit default constructor for 'struct Z1', because const member 'c1' cannot be default-initialized}}
+Z1 z1; // expected-note {{first required here}}
diff --git a/test/SemaCXX/dependent-types.cpp b/test/SemaCXX/dependent-types.cpp
index b2a5c45787c9..300312580a8f 100644
--- a/test/SemaCXX/dependent-types.cpp
+++ b/test/SemaCXX/dependent-types.cpp
@@ -4,7 +4,7 @@ template<typename T, int Size> void f() {
T x1;
T* x2;
T& x3; // expected-error{{declaration of reference variable 'x3' requires an initializer}}
- T x4[]; // expected-error{{variable has incomplete type 'T []'}}
+ T x4[]; // expected-error{{needs an explicit size or an initializer}}
T x5[Size];
int x6[Size];
}
diff --git a/test/SemaCXX/format-attribute.cpp b/test/SemaCXX/format-attribute.cpp
new file mode 100644
index 000000000000..a21ebe113066
--- /dev/null
+++ b/test/SemaCXX/format-attribute.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// PR5521
+struct A { void a(const char*,...) __attribute((format(printf,2,3))); };
+void b(A x) {
+ x.a("%d", 3);
+}
+struct X { void a(const char*,...) __attribute((format(printf,1,3))); }; // expected-error {{format argument not a string type}}
diff --git a/test/SemaCXX/friend-class-nodecl.cpp b/test/SemaCXX/friend-class-nodecl.cpp
index de12eaf741c5..13330f815db7 100644
--- a/test/SemaCXX/friend-class-nodecl.cpp
+++ b/test/SemaCXX/friend-class-nodecl.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -ast-print %s -o %t &&
+// RUN: clang-cc -ast-print %s -o %t
// RUN: not grep '^ *class B' %t
// Tests that the tag decls in friend declarations aren't added to the
diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp
index b4c72f557d2a..fc9b3ab51ead 100644
--- a/test/SemaCXX/linkage-spec.cpp
+++ b/test/SemaCXX/linkage-spec.cpp
@@ -32,4 +32,11 @@ extern "C++" {
int foo(int x) { return x; }
};
}
-} \ No newline at end of file
+}
+
+// PR5430
+namespace pr5430 {
+ extern "C" void func(void);
+}
+using namespace pr5430;
+extern "C" void pr5430::func(void) { }
diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp
index 069f52605b92..cd13bcc3670e 100644
--- a/test/SemaCXX/member-expr.cpp
+++ b/test/SemaCXX/member-expr.cpp
@@ -28,8 +28,7 @@ struct B {
A *f0();
};
int f0(B *b) {
- return b->f0->f0; // expected-error{{member reference base type 'struct A *()' is not a structure or union}} \
- // expected-note{{perhaps you meant to call this function}}
+ return b->f0->f0; // expected-error{{perhaps you meant to call this function}}
}
int i;
diff --git a/test/SemaCXX/member-pointer-size.cpp b/test/SemaCXX/member-pointer-size.cpp
index f86e72b288cd..952027d12395 100644
--- a/test/SemaCXX/member-pointer-size.cpp
+++ b/test/SemaCXX/member-pointer-size.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify &&
+// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify
// RUN: clang-cc -triple i686-unknown-unknown %s -fsyntax-only -verify
#include <stddef.h>
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 6f3e9effe538..ededfc0900de 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -119,13 +119,13 @@ void test_delete_conv(X0 x0, X1 x1, X2 x2) {
// PR4782
class X3 {
public:
- static void operator delete(void * mem, unsigned long size);
+ static void operator delete(void * mem, size_t size);
};
class X4 {
public:
static void release(X3 *x);
- static void operator delete(void * mem, unsigned long size);
+ static void operator delete(void * mem, size_t size);
};
@@ -137,3 +137,56 @@ class X5 {
public:
void Destroy() const { delete this; }
};
+
+class Base {
+public:
+ static int operator new(signed char) throw(); // expected-error {{'operator new' takes type size_t}} \
+ // expected-error {{operator new' must return type 'void *'}}
+ static int operator new[] (signed char) throw(); // expected-error {{'operator new[]' takes type size_t}} \
+ // expected-error {{operator new[]' must return type 'void *'}}
+};
+
+class Tier {};
+class Comp : public Tier {};
+
+class Thai : public Base {
+public:
+ Thai(const Tier *adoptDictionary);
+};
+
+void loadEngineFor() {
+ const Comp *dict;
+ new Thai(dict);
+}
+
+template <class T> struct TBase {
+ void* operator new(T size, int); // expected-error {{'operator new' takes type size_t}}
+};
+
+TBase<int> t1; // expected-note {{in instantiation of template class 'struct TBase<int>' requested here}}
+
+class X6 {
+public:
+ static void operator delete(void*, int); // expected-note {{member found by ambiguous name lookup}}
+};
+
+class X7 {
+public:
+ static void operator delete(void*, int); // expected-note {{member found by ambiguous name lookup}}
+};
+
+class X8 : public X6, public X7 {
+};
+
+void f(X8 *x8) {
+ delete x8; // expected-error {{member 'operator delete' found in multiple base classes of different types}}
+}
+
+class X9 {
+ static void operator delete(void*, int); // expected-note {{'operator delete' declared here}}
+ static void operator delete(void*, float); // expected-note {{'operator delete' declared here}}
+};
+
+void f(X9 *x9) {
+ delete x9; // expected-error {{no suitable member 'operator delete' in 'X9'}}
+}
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index 94f352efc76c..3a0bf3008d6c 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -278,3 +278,16 @@ float& db_rebind(Z&);
void db_rebind_test(Z2 z2) {
float& f1 = db_rebind(z2);
}
+
+class string { };
+class opt : public string { };
+
+struct SR {
+ SR(const string&);
+};
+
+void f(SR) { }
+
+void g(opt o) {
+ f(o);
+}
diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp
index 13777daf2d20..fd0cbc6c8643 100644
--- a/test/SemaCXX/overloaded-builtin-operators.cpp
+++ b/test/SemaCXX/overloaded-builtin-operators.cpp
@@ -175,3 +175,16 @@ void test_dr425(A a) {
(void)(1.0f * a); // expected-error{{ambiguous}} \
// expected-note 81{{candidate}}
}
+
+// pr5432
+enum e {X};
+
+const int a[][2] = {{1}};
+
+int test_pr5432() {
+ return a[X][X];
+}
+
+void f() {
+ (void)__extension__(A());
+}
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index 750038d4ab51..7762667d1aba 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -164,7 +164,11 @@ struct Callable2 {
double& operator()(...) const;
};
-void test_callable(Callable c, Callable2 c2, const Callable2& c2c) {
+struct DerivesCallable : public Callable {
+};
+
+void test_callable(Callable c, Callable2 c2, const Callable2& c2c,
+ DerivesCallable dc) {
int &ir = c(1);
float &fr = c(1, 3.14159, 17, 42);
@@ -175,6 +179,9 @@ void test_callable(Callable c, Callable2 c2, const Callable2& c2c) {
int &ir2 = c2();
int &ir3 = c2(1);
double &fr2 = c2c();
+
+ int &ir4 = dc(17);
+ double &fr3 = dc(3.14159f);
}
typedef float FLOAT;
diff --git a/test/SemaCXX/pseudo-destructors.cpp b/test/SemaCXX/pseudo-destructors.cpp
index 1f05e81df530..0850c44a36f9 100644
--- a/test/SemaCXX/pseudo-destructors.cpp
+++ b/test/SemaCXX/pseudo-destructors.cpp
@@ -37,4 +37,4 @@ typedef int Integer;
void destroy_without_call(int *ip) {
ip->~Integer; // expected-error{{called immediately}}
-} \ No newline at end of file
+}
diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp
index d816c05e3ee3..d3962727b806 100644
--- a/test/SemaCXX/static-cast.cpp
+++ b/test/SemaCXX/static-cast.cpp
@@ -1,11 +1,10 @@
// RUN: clang-cc -fsyntax-only -verify -faccess-control %s
-
struct A {};
struct B : public A {}; // Single public base.
struct C1 : public virtual B {}; // Single virtual base.
struct C2 : public virtual B {};
struct D : public C1, public C2 {}; // Diamond
-struct E : private A {}; // Single private base. expected-note 2 {{'private' inheritance specifier here}}
+struct E : private A {}; // Single private base. expected-note 3 {{'private' inheritance specifier here}}
struct F : public C1 {}; // Single path to B with virtual.
struct G1 : public B {};
struct G2 : public B {};
@@ -57,8 +56,8 @@ void t_529_2()
// Bad code below
(void)static_cast<void*>((const int*)0); // expected-error {{static_cast from 'int const *' to 'void *' is not allowed}}
- //(void)static_cast<A*>((E*)0); // {{static_cast from 'struct E *' to 'struct A *' is not allowed}}
- //(void)static_cast<A*>((H*)0); // {{static_cast from 'struct H *' to 'struct A *' is not allowed}}
+ (void)static_cast<A*>((E*)0); // expected-error {{inaccessible base class 'struct A'}}
+ (void)static_cast<A*>((H*)0); // expected-error {{ambiguous conversion}}
(void)static_cast<int>((int*)0); // expected-error {{static_cast from 'int *' to 'int' is not allowed}}
(void)static_cast<A**>((B**)0); // expected-error {{static_cast from 'struct B **' to 'struct A **' is not allowed}}
(void)static_cast<char&>(i); // expected-error {{non-const lvalue reference to type 'char' cannot be initialized with a value of type 'int'}}
@@ -144,3 +143,38 @@ namespace pr5261 {
};
outer<int> EntryList;
}
+
+
+// Initialization by constructor
+struct X0;
+
+struct X1 {
+ X1();
+ X1(X1&);
+ X1(const X0&);
+
+ operator X0() const;
+};
+
+struct X0 { };
+
+void test_ctor_init() {
+ (void)static_cast<X1>(X1());
+}
+
+// Casting away constness
+struct X2 {
+};
+
+struct X3 : X2 {
+};
+
+struct X4 {
+ typedef const X3 X3_typedef;
+
+ void f() const {
+ (void)static_cast<X3_typedef*>(x2);
+ }
+
+ const X2 *x2;
+};
diff --git a/test/SemaCXX/using-decl-1.cpp b/test/SemaCXX/using-decl-1.cpp
index 37e101e221ea..42deb27027bf 100644
--- a/test/SemaCXX/using-decl-1.cpp
+++ b/test/SemaCXX/using-decl-1.cpp
@@ -17,3 +17,24 @@ namespace N {
void f(int) { } // expected-error{{redefinition}}
}
+
+namespace N {
+ void f(double);
+ void f(long);
+}
+
+struct X0 {
+ void operator()(int);
+ void operator()(long);
+};
+
+struct X1 : X0 {
+ // FIXME: give this operator() a 'float' parameter to test overloading
+ // behavior. It currently fails.
+ void operator()();
+ using X0::operator();
+
+ void test() {
+ (*this)(1);
+ }
+};
diff --git a/test/SemaCXX/using-decl-templates.cpp b/test/SemaCXX/using-decl-templates.cpp
index 1a53704c1e68..684009b78a43 100644
--- a/test/SemaCXX/using-decl-templates.cpp
+++ b/test/SemaCXX/using-decl-templates.cpp
@@ -2,12 +2,12 @@
template<typename T> struct A {
void f() { }
- struct N { };
+ struct N { }; // expected-note{{target of using declaration}}
};
template<typename T> struct B : A<T> {
using A<T>::f;
- using A<T>::N;
+ using A<T>::N; // expected-error{{dependent using declaration resolved to type without 'typename'}}
using A<T>::foo; // expected-error{{no member named 'foo'}}
using A<double>::f; // expected-error{{using declaration refers into 'A<double>::', which is not a base class of 'B'}}
diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp
index 29d866fa64de..25d708494b1a 100644
--- a/test/SemaCXX/value-initialization.cpp
+++ b/test/SemaCXX/value-initialization.cpp
@@ -1,10 +1,10 @@
// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
-struct A {
+struct A { // expected-error {{implicit default constructor for 'struct A' must explicitly initialize the const member 'i'}}
const int i; // expected-note {{declared at}}
virtual void f() { }
};
int main () {
- (void)A(); // expected-error {{cannot define the implicit default constructor for 'struct A', because const member 'i' cannot be default-initialized}}
+ (void)A(); // expected-note {{first required here}}
}
diff --git a/test/SemaCXX/vararg-default-arg.cpp b/test/SemaCXX/vararg-default-arg.cpp
new file mode 100644
index 000000000000..5ba032027742
--- /dev/null
+++ b/test/SemaCXX/vararg-default-arg.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc %s -verify -fsyntax-only
+// PR5462
+
+void f1(void);
+void f2(const char * = __null, ...);
+
+void f1(void)
+{
+ f2();
+}
diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
index 390f58b1b7b3..977df144fa11 100644
--- a/test/SemaCXX/vararg-non-pod.cpp
+++ b/test/SemaCXX/vararg-non-pod.cpp
@@ -65,4 +65,4 @@ void t5()
E e(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic constructor; call will abort at runtime}}
(void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic constructor; call will abort at runtime}}
-} \ No newline at end of file
+}
diff --git a/test/SemaCXX/warn-for-var-in-else.cpp b/test/SemaCXX/warn-for-var-in-else.cpp
index f73c60689446..c46b30640fb2 100644
--- a/test/SemaCXX/warn-for-var-in-else.cpp
+++ b/test/SemaCXX/warn-for-var-in-else.cpp
@@ -2,6 +2,7 @@
// rdar://6425550
int bar();
void do_something(int);
+int *get_ptr();
int foo() {
if (int X = bar()) {
@@ -25,7 +26,20 @@ bool foo2() {
do_something(B); // expected-warning{{'B' is always false in this context}}
} else if (B2) { // expected-warning{{'B2' is always false in this context}}
do_something(B); // expected-warning{{'B' is always false in this context}}
+ do_something(B2); // expected-warning{{'B2' is always false in this context}}
}
return B; // expected-warning{{'B' is always false in this context}}
}
}
+
+void foo3() {
+ if (int *P1 = get_ptr())
+ do_something(*P1);
+ else if (int *P2 = get_ptr()) {
+ do_something(*P1); // expected-warning{{'P1' is always NULL in this context}}
+ do_something(*P2);
+ } else {
+ do_something(*P1); // expected-warning{{'P1' is always NULL in this context}}
+ do_something(*P2); // expected-warning{{'P2' is always NULL in this context}}
+ }
+}
diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp
index d8b9a00ad6de..019863686d32 100644
--- a/test/SemaCXX/warn-unused-variables.cpp
+++ b/test/SemaCXX/warn-unused-variables.cpp
@@ -4,3 +4,31 @@ template<typename T> void f() {
T t;
t = 17;
}
+
+// PR5407
+struct A { A(); };
+struct B { ~B(); };
+void f() {
+ A a;
+ B b;
+}
+
+// PR5531
+namespace PR5531 {
+ struct A {
+ };
+
+ struct B {
+ B(int);
+ };
+
+ struct C {
+ ~C();
+ };
+
+ void test() {
+ A();
+ B(17);
+ C();
+ }
+}
diff --git a/test/SemaObjC/atomoic-property-synnthesis-rules.m b/test/SemaObjC/atomoic-property-synnthesis-rules.m
new file mode 100644
index 000000000000..429d6c0f804d
--- /dev/null
+++ b/test/SemaObjC/atomoic-property-synnthesis-rules.m
@@ -0,0 +1,369 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+/*
+ Conditions for warning:
+ 1. the property is atomic
+ 2. the current @implementation contains an @synthesize for the property
+ 3. the current @implementation contains a hand-written setter XOR getter
+ 4. the property is read-write
+
+ Cases marked WARN should warn one the following:
+ warning: Atomic property 'x' has a synthesized setter and a
+ manually-implemented getter, which may break atomicity.
+ warning: Atomic property 'x' has a synthesized getter and a
+ manually-implemented setter, which may break atomicity.
+
+ Cases not marked WARN only satisfy the indicated subset
+ of the conditions required to warn.
+
+ There should be 8 warnings.
+*/
+
+@interface Foo
+{
+ /* 12 4 */ int GetSet;
+ /* WARN */ int Get;
+ /* WARN */ int Set;
+ /* 12 4 */ int None;
+ /* 2 4 */ int GetSet_Nonatomic;
+ /* 234 */ int Get_Nonatomic;
+ /* 234 */ int Set_Nonatomic;
+ /* 2 4 */ int None_Nonatomic;
+
+ /* 12 */ int GetSet_ReadOnly;
+ /* 123 */ int Get_ReadOnly;
+ /* 123 */ int Set_ReadOnly;
+ /* 12 */ int None_ReadOnly;
+ /* 2 */ int GetSet_Nonatomic_ReadOnly;
+ /* 23 */ int Get_Nonatomic_ReadOnly;
+ /* 23 */ int Set_Nonatomic_ReadOnly;
+ /* 2 */ int None_Nonatomic_ReadOnly;
+
+ /* 12 4 */ int GetSet_ReadWriteInExt;
+ /* WARN */ int Get_ReadWriteInExt;
+ /* WARN */ int Set_ReadWriteInExt;
+ /* 12 4 */ int None_ReadWriteInExt;
+ /* 2 4 */ int GetSet_Nonatomic_ReadWriteInExt;
+ /* 234 */ int Get_Nonatomic_ReadWriteInExt;
+ /* 234 */ int Set_Nonatomic_ReadWriteInExt;
+ /* 2 4 */ int None_Nonatomic_ReadWriteInExt;
+
+
+ /* 12 4 */ int GetSet_LateSynthesize;
+ /* WARN */ int Get_LateSynthesize;
+ /* WARN */ int Set_LateSynthesize;
+ /* 12 4 */ int None_LateSynthesize;
+ /* 2 4 */ int GetSet_Nonatomic_LateSynthesize;
+ /* 234 */ int Get_Nonatomic_LateSynthesize;
+ /* 234 */ int Set_Nonatomic_LateSynthesize;
+ /* 2 4 */ int None_Nonatomic_LateSynthesize;
+
+ /* 12 */ int GetSet_ReadOnly_LateSynthesize;
+ /* 123 */ int Get_ReadOnly_LateSynthesize;
+ /* 123 */ int Set_ReadOnly_LateSynthesize;
+ /* 12 */ int None_ReadOnly_LateSynthesize;
+ /* 2 */ int GetSet_Nonatomic_ReadOnly_LateSynthesize;
+ /* 23 */ int Get_Nonatomic_ReadOnly_LateSynthesize;
+ /* 23 */ int Set_Nonatomic_ReadOnly_LateSynthesize;
+ /* 2 */ int None_Nonatomic_ReadOnly_LateSynthesize;
+
+ /* 12 4 */ int GetSet_ReadWriteInExt_LateSynthesize;
+ /* WARN */ int Get_ReadWriteInExt_LateSynthesize;
+ /* WARN */ int Set_ReadWriteInExt_LateSynthesize;
+ /* 12 4 */ int None_ReadWriteInExt_LateSynthesize;
+ /* 2 4 */ int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
+ /* 234 */ int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
+ /* 234 */ int Set_Nonatomic_ReadWriteInExt_LateSynthesize;
+ /* 2 4 */ int None_Nonatomic_ReadWriteInExt_LateSynthesize;
+
+
+ /* 1 4 */ int GetSet_NoSynthesize;
+ /* 1 34 */ int Get_NoSynthesize;
+ /* 1 34 */ int Set_NoSynthesize;
+ /* 1 4 */ int None_NoSynthesize;
+ /* 4 */ int GetSet_Nonatomic_NoSynthesize;
+ /* 34 */ int Get_Nonatomic_NoSynthesize;
+ /* 34 */ int Set_Nonatomic_NoSynthesize;
+ /* 4 */ int None_Nonatomic_NoSynthesize;
+
+ /* 1 */ int GetSet_ReadOnly_NoSynthesize;
+ /* 1 3 */ int Get_ReadOnly_NoSynthesize;
+ /* 1 3 */ int Set_ReadOnly_NoSynthesize;
+ /* 1 */ int None_ReadOnly_NoSynthesize;
+ /* */ int GetSet_Nonatomic_ReadOnly_NoSynthesize;
+ /* 3 */ int Get_Nonatomic_ReadOnly_NoSynthesize;
+ /* 3 */ int Set_Nonatomic_ReadOnly_NoSynthesize;
+ /* */ int None_Nonatomic_ReadOnly_NoSynthesize;
+
+ /* 1 4 */ int GetSet_ReadWriteInExt_NoSynthesize;
+ /* 1 34 */ int Get_ReadWriteInExt_NoSynthesize;
+ /* 1 34 */ int Set_ReadWriteInExt_NoSynthesize;
+ /* 1 4 */ int None_ReadWriteInExt_NoSynthesize;
+ /* 4 */ int GetSet_Nonatomic_ReadWriteInExt_NoSynthesize;
+ /* 34 */ int Get_Nonatomic_ReadWriteInExt_NoSynthesize;
+ /* 34 */ int Set_Nonatomic_ReadWriteInExt_NoSynthesize;
+ /* 4 */ int None_Nonatomic_ReadWriteInExt_NoSynthesize;
+}
+
+// read-write - might warn
+@property int GetSet;
+@property int Get; // expected-note {{property declared here}}
+@property int Set; // expected-note {{property declared here}}
+@property int None;
+@property(nonatomic) int GetSet_Nonatomic;
+@property(nonatomic) int Get_Nonatomic;
+@property(nonatomic) int Set_Nonatomic;
+@property(nonatomic) int None_Nonatomic;
+
+// read-only - must not warn
+@property(readonly) int GetSet_ReadOnly;
+@property(readonly) int Get_ReadOnly;
+@property(readonly) int Set_ReadOnly;
+@property(readonly) int None_ReadOnly;
+@property(nonatomic,readonly) int GetSet_Nonatomic_ReadOnly;
+@property(nonatomic,readonly) int Get_Nonatomic_ReadOnly;
+@property(nonatomic,readonly) int Set_Nonatomic_ReadOnly;
+@property(nonatomic,readonly) int None_Nonatomic_ReadOnly;
+
+// read-only in class, read-write in class extension - might warn
+@property(readonly) int GetSet_ReadWriteInExt;
+@property(readonly) int Get_ReadWriteInExt; // expected-note {{property declared here}}
+@property(readonly) int Set_ReadWriteInExt; // expected-note {{property declared here}}
+@property(readonly) int None_ReadWriteInExt;
+@property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt;
+@property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt;
+@property(nonatomic,readonly) int Set_Nonatomic_ReadWriteInExt;
+@property(nonatomic,readonly) int None_Nonatomic_ReadWriteInExt;
+
+
+// same as above, but @synthesize follows the hand-written methods - might warn
+@property int GetSet_LateSynthesize;
+@property int Get_LateSynthesize; // expected-note {{property declared here}}
+@property int Set_LateSynthesize; // expected-note {{property declared here}}
+@property int None_LateSynthesize;
+@property(nonatomic) int GetSet_Nonatomic_LateSynthesize;
+@property(nonatomic) int Get_Nonatomic_LateSynthesize;
+@property(nonatomic) int Set_Nonatomic_LateSynthesize;
+@property(nonatomic) int None_Nonatomic_LateSynthesize;
+
+@property(readonly) int GetSet_ReadOnly_LateSynthesize;
+@property(readonly) int Get_ReadOnly_LateSynthesize;
+@property(readonly) int Set_ReadOnly_LateSynthesize;
+@property(readonly) int None_ReadOnly_LateSynthesize;
+@property(nonatomic,readonly) int GetSet_Nonatomic_ReadOnly_LateSynthesize;
+@property(nonatomic,readonly) int Get_Nonatomic_ReadOnly_LateSynthesize;
+@property(nonatomic,readonly) int Set_Nonatomic_ReadOnly_LateSynthesize;
+@property(nonatomic,readonly) int None_Nonatomic_ReadOnly_LateSynthesize;
+
+@property(readonly) int GetSet_ReadWriteInExt_LateSynthesize;
+@property(readonly) int Get_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}}
+@property(readonly) int Set_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}}
+@property(readonly) int None_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readonly) int Set_Nonatomic_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readonly) int None_Nonatomic_ReadWriteInExt_LateSynthesize;
+
+
+// same as above, but with no @synthesize - must not warn
+@property int GetSet_NoSynthesize;
+@property int Get_NoSynthesize;
+@property int Set_NoSynthesize;
+@property int None_NoSynthesize;
+@property(nonatomic) int GetSet_Nonatomic_NoSynthesize;
+@property(nonatomic) int Get_Nonatomic_NoSynthesize;
+@property(nonatomic) int Set_Nonatomic_NoSynthesize;
+@property(nonatomic) int None_Nonatomic_NoSynthesize;
+
+@property(readonly) int GetSet_ReadOnly_NoSynthesize;
+@property(readonly) int Get_ReadOnly_NoSynthesize;
+@property(readonly) int Set_ReadOnly_NoSynthesize;
+@property(readonly) int None_ReadOnly_NoSynthesize;
+@property(nonatomic,readonly) int GetSet_Nonatomic_ReadOnly_NoSynthesize;
+@property(nonatomic,readonly) int Get_Nonatomic_ReadOnly_NoSynthesize;
+@property(nonatomic,readonly) int Set_Nonatomic_ReadOnly_NoSynthesize;
+@property(nonatomic,readonly) int None_Nonatomic_ReadOnly_NoSynthesize;
+
+@property(readonly) int GetSet_ReadWriteInExt_NoSynthesize;
+@property(readonly) int Get_ReadWriteInExt_NoSynthesize;
+@property(readonly) int Set_ReadWriteInExt_NoSynthesize;
+@property(readonly) int None_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readonly) int Set_Nonatomic_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readonly) int None_Nonatomic_ReadWriteInExt_NoSynthesize;
+
+@end
+
+
+@interface Foo ()
+
+@property(readwrite) int GetSet_ReadWriteInExt;
+@property(readwrite) int Get_ReadWriteInExt;
+@property(readwrite) int Set_ReadWriteInExt;
+@property(readwrite) int None_ReadWriteInExt;
+@property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt;
+@property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt;
+@property(nonatomic,readwrite) int Set_Nonatomic_ReadWriteInExt;
+@property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt;
+
+@property(readwrite) int GetSet_ReadWriteInExt_LateSynthesize;
+@property(readwrite) int Get_ReadWriteInExt_LateSynthesize;
+@property(readwrite) int Set_ReadWriteInExt_LateSynthesize;
+@property(readwrite) int None_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readwrite) int Set_Nonatomic_ReadWriteInExt_LateSynthesize;
+@property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt_LateSynthesize;
+
+@property(readwrite) int GetSet_ReadWriteInExt_NoSynthesize;
+@property(readwrite) int Get_ReadWriteInExt_NoSynthesize;
+@property(readwrite) int Set_ReadWriteInExt_NoSynthesize;
+@property(readwrite) int None_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readwrite) int Set_Nonatomic_ReadWriteInExt_NoSynthesize;
+@property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt_NoSynthesize;
+
+@end
+
+@implementation Foo
+
+@synthesize GetSet, Get, Set, None, GetSet_Nonatomic, Get_Nonatomic, Set_Nonatomic, None_Nonatomic;
+@synthesize GetSet_ReadOnly, Get_ReadOnly, Set_ReadOnly, None_ReadOnly, GetSet_Nonatomic_ReadOnly, Get_Nonatomic_ReadOnly, Set_Nonatomic_ReadOnly, None_Nonatomic_ReadOnly;
+@synthesize GetSet_ReadWriteInExt, Get_ReadWriteInExt, Set_ReadWriteInExt, None_ReadWriteInExt, GetSet_Nonatomic_ReadWriteInExt, Get_Nonatomic_ReadWriteInExt, Set_Nonatomic_ReadWriteInExt, None_Nonatomic_ReadWriteInExt;
+
+#define GET(x) \
+ -(int) x { return self->x; }
+#define SET(x) \
+ -(void) set##x:(int)value { self->x = value; }
+
+GET(GetSet)
+SET(GetSet)
+GET(Get) // expected-warning {{writable atomic property 'Get' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+SET(Set) // expected-warning {{writable atomic property 'Set' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+GET(GetSet_Nonatomic)
+SET(GetSet_Nonatomic)
+GET(Get_Nonatomic)
+SET(Set_Nonatomic)
+
+GET(GetSet_ReadOnly)
+SET(GetSet_ReadOnly)
+GET(Get_ReadOnly)
+SET(Set_ReadOnly)
+GET(GetSet_Nonatomic_ReadOnly)
+SET(GetSet_Nonatomic_ReadOnly)
+GET(Get_Nonatomic_ReadOnly)
+SET(Set_Nonatomic_ReadOnly)
+
+GET(GetSet_ReadWriteInExt)
+SET(GetSet_ReadWriteInExt)
+GET(Get_ReadWriteInExt) // expected-warning {{writable atomic property 'Get_ReadWriteInExt' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+SET(Set_ReadWriteInExt) // expected-warning {{writable atomic property 'Set_ReadWriteInExt' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+GET(GetSet_Nonatomic_ReadWriteInExt)
+SET(GetSet_Nonatomic_ReadWriteInExt)
+GET(Get_Nonatomic_ReadWriteInExt)
+SET(Set_Nonatomic_ReadWriteInExt)
+
+
+GET(GetSet_LateSynthesize)
+SET(GetSet_LateSynthesize)
+GET(Get_LateSynthesize) // expected-warning {{writable atomic property 'Get_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+SET(Set_LateSynthesize) // expected-warning {{writable atomic property 'Set_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+GET(GetSet_Nonatomic_LateSynthesize)
+SET(GetSet_Nonatomic_LateSynthesize)
+GET(Get_Nonatomic_LateSynthesize)
+SET(Set_Nonatomic_LateSynthesize)
+
+GET(GetSet_ReadOnly_LateSynthesize)
+SET(GetSet_ReadOnly_LateSynthesize)
+GET(Get_ReadOnly_LateSynthesize)
+SET(Set_ReadOnly_LateSynthesize)
+GET(GetSet_Nonatomic_ReadOnly_LateSynthesize)
+SET(GetSet_Nonatomic_ReadOnly_LateSynthesize)
+GET(Get_Nonatomic_ReadOnly_LateSynthesize)
+SET(Set_Nonatomic_ReadOnly_LateSynthesize)
+
+GET(GetSet_ReadWriteInExt_LateSynthesize)
+SET(GetSet_ReadWriteInExt_LateSynthesize)
+GET(Get_ReadWriteInExt_LateSynthesize) // expected-warning {{writable atomic property 'Get_ReadWriteInExt_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+SET(Set_ReadWriteInExt_LateSynthesize) // expected-warning {{writable atomic property 'Set_ReadWriteInExt_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
+GET(GetSet_Nonatomic_ReadWriteInExt_LateSynthesize)
+SET(GetSet_Nonatomic_ReadWriteInExt_LateSynthesize)
+GET(Get_Nonatomic_ReadWriteInExt_LateSynthesize)
+SET(Set_Nonatomic_ReadWriteInExt_LateSynthesize)
+
+
+GET(GetSet_NoSynthesize)
+SET(GetSet_NoSynthesize)
+GET(Get_NoSynthesize)
+SET(Set_NoSynthesize)
+GET(GetSet_Nonatomic_NoSynthesize)
+SET(GetSet_Nonatomic_NoSynthesize)
+GET(Get_Nonatomic_NoSynthesize)
+SET(Set_Nonatomic_NoSynthesize)
+
+GET(GetSet_ReadOnly_NoSynthesize)
+SET(GetSet_ReadOnly_NoSynthesize)
+GET(Get_ReadOnly_NoSynthesize)
+SET(Set_ReadOnly_NoSynthesize)
+GET(GetSet_Nonatomic_ReadOnly_NoSynthesize)
+SET(GetSet_Nonatomic_ReadOnly_NoSynthesize)
+GET(Get_Nonatomic_ReadOnly_NoSynthesize)
+SET(Set_Nonatomic_ReadOnly_NoSynthesize)
+
+GET(GetSet_ReadWriteInExt_NoSynthesize)
+SET(GetSet_ReadWriteInExt_NoSynthesize)
+GET(Get_ReadWriteInExt_NoSynthesize)
+SET(Set_ReadWriteInExt_NoSynthesize)
+GET(GetSet_Nonatomic_ReadWriteInExt_NoSynthesize)
+SET(GetSet_Nonatomic_ReadWriteInExt_NoSynthesize)
+GET(Get_Nonatomic_ReadWriteInExt_NoSynthesize)
+SET(Set_Nonatomic_ReadWriteInExt_NoSynthesize)
+
+
+// late synthesize - follows getter/setter implementations
+
+@synthesize GetSet_LateSynthesize, Get_LateSynthesize, Set_LateSynthesize, None_LateSynthesize, GetSet_Nonatomic_LateSynthesize, Get_Nonatomic_LateSynthesize, Set_Nonatomic_LateSynthesize, None_Nonatomic_LateSynthesize;
+@synthesize GetSet_ReadOnly_LateSynthesize, Get_ReadOnly_LateSynthesize, Set_ReadOnly_LateSynthesize, None_ReadOnly_LateSynthesize, GetSet_Nonatomic_ReadOnly_LateSynthesize, Get_Nonatomic_ReadOnly_LateSynthesize, Set_Nonatomic_ReadOnly_LateSynthesize, None_Nonatomic_ReadOnly_LateSynthesize;
+@synthesize GetSet_ReadWriteInExt_LateSynthesize, Get_ReadWriteInExt_LateSynthesize, Set_ReadWriteInExt_LateSynthesize, None_ReadWriteInExt_LateSynthesize, GetSet_Nonatomic_ReadWriteInExt_LateSynthesize, Get_Nonatomic_ReadWriteInExt_LateSynthesize, Set_Nonatomic_ReadWriteInExt_LateSynthesize, None_Nonatomic_ReadWriteInExt_LateSynthesize;
+
+// no synthesize - use dynamic instead
+
+@dynamic GetSet_NoSynthesize, Get_NoSynthesize, Set_NoSynthesize, None_NoSynthesize, GetSet_Nonatomic_NoSynthesize, Get_Nonatomic_NoSynthesize, Set_Nonatomic_NoSynthesize, None_Nonatomic_NoSynthesize;
+@dynamic GetSet_ReadOnly_NoSynthesize, Get_ReadOnly_NoSynthesize, Set_ReadOnly_NoSynthesize, None_ReadOnly_NoSynthesize, GetSet_Nonatomic_ReadOnly_NoSynthesize, Get_Nonatomic_ReadOnly_NoSynthesize, Set_Nonatomic_ReadOnly_NoSynthesize, None_Nonatomic_ReadOnly_NoSynthesize;
+@dynamic GetSet_ReadWriteInExt_NoSynthesize, Get_ReadWriteInExt_NoSynthesize, Set_ReadWriteInExt_NoSynthesize, None_ReadWriteInExt_NoSynthesize, GetSet_Nonatomic_ReadWriteInExt_NoSynthesize, Get_Nonatomic_ReadWriteInExt_NoSynthesize, Set_Nonatomic_ReadWriteInExt_NoSynthesize, None_Nonatomic_ReadWriteInExt_NoSynthesize;
+
+@end
+
+/*
+// the following method should cause a warning along the lines of
+// :warning: Atomic property 'x' cannot pair a synthesized setter/getter with a manually implemented setter/getter
+- (void) setX: (int) aValue
+{
+ x = aValue;
+}
+
+// no warning 'cause this is nonatomic
+- (void) setY: (int) aValue
+{
+ y = aValue;
+}
+
+// the following method should cause a warning along the lines of
+// :warning: Atomic property 'x' cannot pair a synthesized setter/getter with a manually implemented setter/getter
+- (int) j
+{
+ return j;
+}
+
+// no warning 'cause this is nonatomic
+- (int) k
+{
+ return k;
+}
+@end
+*/
+int main (int argc, const char * argv[]) {
+ return 0;
+}
diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m
index a481cffd2886..afd35a8e2630 100644
--- a/test/SemaObjC/call-super-2.m
+++ b/test/SemaObjC/call-super-2.m
@@ -6,6 +6,7 @@ typedef struct objc_object *id;
id objc_getClass(const char *s);
@interface Object
+- (id) initWithInt: (int) i;
@end
@protocol Func
@@ -28,6 +29,7 @@ id objc_getClass(const char *s);
- (int) instance_func5;
- (int) instance_func6;
- (int) instance_func7;
+- (id) initWithInt: (int) i;
@end
@implementation Derived
@@ -94,5 +96,13 @@ id objc_getClass(const char *s);
{
return [objc_getClass("Derived") class_func1];
}
+- (id) initWithInt: (int) i
+{
+ // Don't warn about parentheses here.
+ if (self = [super initWithInt: i]) {
+ [self instance_func1];
+ }
+ return self;
+}
@end
diff --git a/test/SemaObjC/class-method-lookup.m b/test/SemaObjC/class-method-lookup.m
index cba93825a4e0..6f745d48ab62 100644
--- a/test/SemaObjC/class-method-lookup.m
+++ b/test/SemaObjC/class-method-lookup.m
@@ -40,7 +40,7 @@
id foo(void) {
Object *obj;
id obj2 = obj;
- [obj setWindow:nil]; // expected-warning {{Object may not respond to 'setWindow:'}}
+ [obj setWindow:nil]; // expected-warning {{Object may not respond to 'setWindow:'}}
return obj;
}
diff --git a/test/SemaObjC/compare-qualified-id.m b/test/SemaObjC/compare-qualified-id.m
index 86845c0358d2..22bec504a558 100644
--- a/test/SemaObjC/compare-qualified-id.m
+++ b/test/SemaObjC/compare-qualified-id.m
@@ -23,11 +23,12 @@ extern NSString * const NSTaskDidTerminateNotification;
- (NSString *)evaluateAsStringInContext:(XCPropertyExpansionContext *)context withNestingState:(const void *)state;
@end
-@implementation XCPropertyExpansionContext
+@implementation XCPropertyExpansionContext // expected-warning {{method definition for 'copyWithZone:' not found}} \
+ // expected-warning {{incomplete implementation}}
- (NSString *)expandedValueForProperty:(NSString *)property {
id <XCPropertyValues> cachedValueNode = [_propNamesToPropValuesCache objectForKey:property]; // expected-warning {{method '-objectForKey:' not found (return type defaults to 'id')}}
if (cachedValueNode == ((void *)0)) { }
NSString * expandedValue = [cachedValueNode evaluateAsStringInContext:self withNestingState:((void *)0)];
return expandedValue;
}
-
+@end
diff --git a/test/SemaObjC/continuation-class-err.m b/test/SemaObjC/continuation-class-err.m
index 262b786b5408..4559696b7f2d 100644
--- a/test/SemaObjC/continuation-class-err.m
+++ b/test/SemaObjC/continuation-class-err.m
@@ -7,11 +7,13 @@
}
@property(readonly) id object; // expected-note {{property declared here}}
@property(readwrite, assign) id object1; // expected-note {{property declared here}}
+@property (readonly) int indentLevel;
@end
@interface ReadOnly ()
@property(readwrite, copy) id object; // expected-warning {{property attribute in continuation class does not match the primary class}}
@property(readonly) id object1; // expected-error {{property declaration in continuation class of 'ReadOnly' is to change a 'readonly' property to 'readwrite'}}
+@property (readwrite, assign) int indentLevel; // OK. assign the the default in any case.
@end
@protocol Proto
diff --git a/test/SemaObjC/deref-interface.m b/test/SemaObjC/deref-interface.m
index 1c85918ed57c..57750a5a4396 100644
--- a/test/SemaObjC/deref-interface.m
+++ b/test/SemaObjC/deref-interface.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -verify -fsyntax-only %s
+// RUN: clang-cc -fobjc-nonfragile-abi -verify -fsyntax-only %s
@interface NSView
- (id)initWithView:(id)realView;
diff --git a/test/SemaObjC/idiomatic-parentheses.m b/test/SemaObjC/idiomatic-parentheses.m
new file mode 100644
index 000000000000..b4c52fa0d146
--- /dev/null
+++ b/test/SemaObjC/idiomatic-parentheses.m
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Don't warn about some common ObjC idioms unless we have -Wparentheses on.
+// <rdar://problem/7382435>
+
+@interface Object
+- (id) init;
+- (id) initWithInt: (int) i;
+- (void) iterate: (id) coll;
+- (id) nextObject;
+@end
+
+@implementation Object
+- (id) init {
+ if (self = [self init]) {
+ }
+ return self;
+}
+
+- (id) initWithInt: (int) i {
+ if (self = [self initWithInt: i]) {
+ }
+ return self;
+}
+
+- (void) iterate: (id) coll {
+ id cur;
+ while (cur = [coll nextObject]) {
+ }
+}
+
+- (id) nextObject {
+ return self;
+}
+@end
diff --git a/test/SemaObjC/ivar-sem-check-2.m b/test/SemaObjC/ivar-sem-check-2.m
index ba6b38934bd1..a5a830d6a3f6 100644
--- a/test/SemaObjC/ivar-sem-check-2.m
+++ b/test/SemaObjC/ivar-sem-check-2.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin10 -verify %s
+// RUN: clang-cc -fsyntax-only -fobjc-nonfragile-abi -verify %s
@interface Super {
id value2; // expected-note {{previously declared 'value2' here}}
diff --git a/test/SemaObjC/method-arg-decay.m b/test/SemaObjC/method-arg-decay.m
index 7fd07d2ede33..e81bcdf7b75f 100644
--- a/test/SemaObjC/method-arg-decay.m
+++ b/test/SemaObjC/method-arg-decay.m
@@ -72,7 +72,9 @@ extern NSMutableArray *XCFindPossibleKeyModules(PBXModule *module, BOOL useExpos
}
- (PBXModule *) moduleForTab:(NSTabViewItem *)item;
@end
-@implementation XCPerspectiveModule
+@implementation XCPerspectiveModule // expected-warning {{method definition for 'moduleForTab:' not found}} \
+ // expected-warning {{method definition for 'performAction:withSelection:' not found}} \
+ // expected-warning {{incomplete implementation}}
+ (void) openForProjectDocument:(PBXProjectDocument *)projectDocument {
}
- (PBXModule *) type:(Class)type inPerspective:(id)perspectiveIdentifer matchingFunction:(BOOL (void *, void *))comparator usingData:(void *)data {
@@ -94,3 +96,4 @@ extern NSMutableArray *XCFindPossibleKeyModules(PBXModule *module, BOOL useExpos
prompts++;
return (BOOL)0;
}
+@end
diff --git a/test/SemaObjC/objc-string-constant.m b/test/SemaObjC/objc-string-constant.m
index d27a46a96632..c6461dd1c25b 100644
--- a/test/SemaObjC/objc-string-constant.m
+++ b/test/SemaObjC/objc-string-constant.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -verify -fsyntax-only
+// RUN: clang-cc -Wsemicolon-before-method-body %s -verify -fsyntax-only
#define nil 0 /* id of Nil instance */
diff --git a/test/SemaObjC/property-category-1.m b/test/SemaObjC/property-category-1.m
index 6695239fd352..fa9d4c8c4bb9 100644
--- a/test/SemaObjC/property-category-1.m
+++ b/test/SemaObjC/property-category-1.m
@@ -24,6 +24,7 @@
- (void) myAnotherobjectSetter : (int)val {
_Anotherobject = val;
}
+- (int) Anotherobject { return _Anotherobject; }
@end
int main(int argc, char **argv) {
diff --git a/test/SemaObjC/property-nonfragile-abi.m b/test/SemaObjC/property-nonfragile-abi.m
index e2de77d3a28c..835209102199 100644
--- a/test/SemaObjC/property-nonfragile-abi.m
+++ b/test/SemaObjC/property-nonfragile-abi.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin9 -verify %s
+// RUN: clang-cc -fsyntax-only -fobjc-nonfragile-abi -verify %s
typedef signed char BOOL;
diff --git a/test/SemaObjC/sizeof-interface.m b/test/SemaObjC/sizeof-interface.m
index 140a980311e4..aeb1b3facb73 100644
--- a/test/SemaObjC/sizeof-interface.m
+++ b/test/SemaObjC/sizeof-interface.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -verify -fsyntax-only %s
+// RUN: clang-cc -fobjc-nonfragile-abi -verify -fsyntax-only %s
@class I0;
diff --git a/test/SemaObjC/static-ivar-ref-1.m b/test/SemaObjC/static-ivar-ref-1.m
index 6b1a31226b20..7e07c7cb99a2 100644
--- a/test/SemaObjC/static-ivar-ref-1.m
+++ b/test/SemaObjC/static-ivar-ref-1.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-unknown-unknown -ast-print %s &&
+// RUN: clang-cc -triple i386-unknown-unknown -ast-print %s
// RUN: clang-cc -triple x86_64-apple-darwin10 -ast-print %s
@interface current
diff --git a/test/SemaObjC/string.m b/test/SemaObjC/string.m
index 3f078f6543ee..3c09c3c03622 100644
--- a/test/SemaObjC/string.m
+++ b/test/SemaObjC/string.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -verify -fsyntax-only &&
+// RUN: clang-cc %s -verify -fsyntax-only
// RUN: clang-cc %s -verify -fsyntax-only -DDECLAREIT
// a declaration of NSConstantString is not required.
diff --git a/test/SemaObjC/synthesized-ivar.m b/test/SemaObjC/synthesized-ivar.m
index de44857934fc..305629b43ce6 100644
--- a/test/SemaObjC/synthesized-ivar.m
+++ b/test/SemaObjC/synthesized-ivar.m
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin9 -verify %s
+// RUN: clang-cc -fsyntax-only -fobjc-nonfragile-abi -verify %s
@interface I
{
}
diff --git a/test/SemaObjC/unused.m b/test/SemaObjC/unused.m
index bbe3109a2817..4e85894b0a1b 100644
--- a/test/SemaObjC/unused.m
+++ b/test/SemaObjC/unused.m
@@ -1,5 +1,6 @@
// RUN: clang-cc %s -verify -Wunused -fsyntax-only
-#include <stdio.h>
+
+int printf(const char *, ...);
@interface Greeter
+ (void) hello;
@@ -7,7 +8,7 @@
@implementation Greeter
+ (void) hello {
- fprintf(stdout, "Hello, World!\n");
+ printf("Hello, World!\n");
}
@end
diff --git a/test/SemaObjC/warn-selector-selection.m b/test/SemaObjC/warn-selector-selection.m
index 4ab89b7e1e2c..4918de77dc7b 100644
--- a/test/SemaObjC/warn-selector-selection.m
+++ b/test/SemaObjC/warn-selector-selection.m
@@ -10,5 +10,5 @@
void foo(void) {
Object *obj;
- [obj setWindow:0]; // expected-warning{{Object may not respond to 'setWindow:'}}
+ [obj setWindow:0]; // expected-warning{{Object may not respond to 'setWindow:'}}
}
diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp
index d2e90c1daa8f..a8163127b000 100644
--- a/test/SemaTemplate/class-template-decl.cpp
+++ b/test/SemaTemplate/class-template-decl.cpp
@@ -41,15 +41,13 @@ struct test {}; // expected-note{{previous definition}}
template<typename T>
struct test : T {}; // expected-error{{redefinition}}
-#if 0
-// FIXME: parse template declarations in these scopes, so that we can
-// complain about the one at function scope.
class X {
public:
template<typename T> class C;
};
void f() {
- template<typename T> class X;
+ template<typename T> class X; // expected-error{{expression}}
}
-#endif
+
+template<typename T> class X1 { } var; // expected-error{{declared as a template}}
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index 4cd43b469ae0..2808404b1d99 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -19,7 +19,7 @@ int test_specs(A<float, float> *a1, A<float, int> *a2) {
int test_incomplete_specs(A<double, double> *a1,
A<double> *a2)
{
- (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
+ (void)a1->x; // expected-error{{member access into incomplete type}}
(void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
}
@@ -104,3 +104,8 @@ Foo<int>* v;
Foo<int>& F() { return *v; }
template <typename T> class Foo {};
Foo<int> x;
+
+
+// Template template parameters
+template<template<class T> class Wibble>
+class Wibble<int> { }; // expected-error{{cannot specialize a template template parameter}}
diff --git a/test/SemaTemplate/constructor-template.cpp b/test/SemaTemplate/constructor-template.cpp
index 79bf7c585e34..12c6f8b9c101 100644
--- a/test/SemaTemplate/constructor-template.cpp
+++ b/test/SemaTemplate/constructor-template.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
struct X0 { // expected-note{{candidate}}
X0(int); // expected-note{{candidate}}
template<typename T> X0(T);
@@ -52,3 +51,34 @@ template<class C> struct A {};
template <> struct A<int>{A(const A<int>&);};
struct B { A<int> x; B(B& a) : x(a.x) {} };
+struct X2 {
+ X2();
+ X2(X2&);
+ template<typename T> X2(T);
+};
+
+X2 test(bool Cond, X2 x2) {
+ if (Cond)
+ return x2; // okay, uses copy constructor
+
+ return X2(); // expected-error{{incompatible type}}
+}
+
+struct X3 {
+ template<typename T> X3(T);
+};
+
+template<> X3::X3(X3); // expected-error{{must pass its first argument by reference}}
+
+struct X4 {
+ X4();
+ ~X4();
+ X4(X4&);
+ template<typename T> X4(const T&, int = 17);
+};
+
+X4 test_X4(bool Cond, X4 x4) {
+ X4 a(x4, 17); // okay, constructor template
+ X4 b(x4); // okay, copy constructor
+ return X4(); // expected-error{{incompatible type}}
+}
diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp
new file mode 100644
index 000000000000..7b7e18f74aec
--- /dev/null
+++ b/test/SemaTemplate/deduction.cpp
@@ -0,0 +1,83 @@
+// RUN: clang-cc -fsyntax-only %s
+
+// Template argument deduction with template template parameters.
+template<typename T, template<T> class A>
+struct X0 {
+ static const unsigned value = 0;
+};
+
+template<template<int> class A>
+struct X0<int, A> {
+ static const unsigned value = 1;
+};
+
+template<int> struct X0i;
+template<long> struct X0l;
+int array_x0a[X0<long, X0l>::value == 0? 1 : -1];
+int array_x0b[X0<int, X0i>::value == 1? 1 : -1];
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+template<typename T> struct allocator { };
+template<typename T, typename Alloc = allocator<T> > struct vector {};
+
+// Fun with meta-lambdas!
+struct _1 {};
+struct _2 {};
+
+// Replaces all occurrences of _1 with Arg1 and _2 with Arg2 in T.
+template<typename T, typename Arg1, typename Arg2>
+struct Replace {
+ typedef T type;
+};
+
+// Replacement of the whole type.
+template<typename Arg1, typename Arg2>
+struct Replace<_1, Arg1, Arg2> {
+ typedef Arg1 type;
+};
+
+template<typename Arg1, typename Arg2>
+struct Replace<_2, Arg1, Arg2> {
+ typedef Arg2 type;
+};
+
+// Replacement through cv-qualifiers
+template<typename T, typename Arg1, typename Arg2>
+struct Replace<const T, Arg1, Arg2> {
+ typedef typename Replace<T, Arg1, Arg2>::type const type;
+};
+
+// Replacement of templates
+template<template<typename> class TT, typename T1, typename Arg1, typename Arg2>
+struct Replace<TT<T1>, Arg1, Arg2> {
+ typedef TT<typename Replace<T1, Arg1, Arg2>::type> type;
+};
+
+template<template<typename, typename> class TT, typename T1, typename T2,
+ typename Arg1, typename Arg2>
+struct Replace<TT<T1, T2>, Arg1, Arg2> {
+ typedef TT<typename Replace<T1, Arg1, Arg2>::type,
+ typename Replace<T2, Arg1, Arg2>::type> type;
+};
+
+// Just for kicks...
+template<template<typename, typename> class TT, typename T1,
+ typename Arg1, typename Arg2>
+struct Replace<TT<T1, _2>, Arg1, Arg2> {
+ typedef TT<typename Replace<T1, Arg1, Arg2>::type, Arg2> type;
+};
+
+int array0[is_same<Replace<_1, int, float>::type, int>::value? 1 : -1];
+int array1[is_same<Replace<const _1, int, float>::type, const int>::value? 1 : -1];
+int array2[is_same<Replace<vector<_1>, int, float>::type, vector<int> >::value? 1 : -1];
+int array3[is_same<Replace<vector<const _1>, int, float>::type, vector<const int> >::value? 1 : -1];
+int array4[is_same<Replace<vector<int, _2>, double, float>::type, vector<int, float> >::value? 1 : -1];
diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp
index 33677aab73ac..0247ddc0ef28 100644
--- a/test/SemaTemplate/default-arguments.cpp
+++ b/test/SemaTemplate/default-arguments.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
template<typename T, int N = 2> struct X; // expected-note{{template is declared here}}
X<int, 1> *x1;
@@ -42,3 +41,83 @@ template<>
struct B<void> {
typedef B<void*> type;
};
+
+// Nested default arguments for template parameters.
+template<typename T> struct X1 { };
+
+template<typename T>
+struct X2 {
+ template<typename U = typename X1<T>::type> // expected-error{{no type named}}
+ struct Inner1 { };
+
+ template<T Value = X1<T>::value> // expected-error{{no member named 'value'}}
+ struct NonType1 { };
+
+ template<T Value>
+ struct Inner2 { };
+
+ template<typename U>
+ struct Inner3 {
+ template<typename X = T, typename V = U>
+ struct VeryInner { };
+
+ template<T Value1 = sizeof(T), T Value2 = sizeof(U),
+ T Value3 = Value1 + Value2>
+ struct NonType2 { };
+ };
+};
+
+X2<int> x2i;
+X2<int>::Inner1<float> x2iif;
+
+X2<int>::Inner1<> x2bad; // expected-note{{instantiation of default argument}}
+
+X2<int>::NonType1<'a'> x2_nontype1;
+X2<int>::NonType1<> x2_nontype1_bad; // expected-note{{instantiation of default argument}}
+
+// Check multi-level substitution into template type arguments
+X2<int>::Inner3<float>::VeryInner<> vi;
+X2<char>::Inner3<int>::NonType2<> x2_deep_nontype;
+
+template<typename T, typename U>
+struct is_same { static const bool value = false; };
+
+template<typename T>
+struct is_same<T, T> { static const bool value = true; };
+
+int array1[is_same<__typeof__(vi),
+ X2<int>::Inner3<float>::VeryInner<int, float> >::value? 1 : -1];
+
+int array2[is_same<__typeof(x2_deep_nontype),
+ X2<char>::Inner3<int>::NonType2<sizeof(char), sizeof(int),
+ sizeof(char)+sizeof(int)> >::value? 1 : -1];
+
+// Template template parameter defaults
+template<template<typename T> class X = X2> struct X3 { };
+int array3[is_same<X3<>, X3<X2> >::value? 1 : -1];
+
+struct add_pointer {
+ template<typename T>
+ struct apply {
+ typedef T* type;
+ };
+};
+
+template<typename T, template<typename> class X = T::template apply>
+ struct X4;
+int array4[is_same<X4<add_pointer>,
+ X4<add_pointer, add_pointer::apply> >::value? 1 : -1];
+
+template<int> struct X5 {}; // expected-note{{has a different type 'int'}}
+template<long> struct X5b {};
+template<typename T,
+ template<T> class B = X5> // expected-error{{template template argument has different}} \
+ // expected-note{{previous non-type template parameter}}
+ struct X6 {};
+
+X6<int> x6a;
+X6<long> x6b; // expected-note{{while checking a default template argument}}
+X6<long, X5b> x6c;
+
+
+template<template<class> class X = B<int> > struct X7; // expected-error{{must be a class template}}
diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp
index 9c0f1ecf0c3b..34ac2d967efc 100644
--- a/test/SemaTemplate/default-expr-arguments.cpp
+++ b/test/SemaTemplate/default-expr-arguments.cpp
@@ -65,8 +65,8 @@ void test_x0(X0<int> xi) {
xi.f(17);
}
-struct NotDefaultConstructible { // expected-note{{candidate}}
- NotDefaultConstructible(int); // expected-note{{candidate}}
+struct NotDefaultConstructible { // expected-note 2{{candidate}}
+ NotDefaultConstructible(int); // expected-note 2{{candidate}}
};
void test_x0_not_default_constructible(X0<NotDefaultConstructible> xn) {
@@ -85,6 +85,18 @@ void test_X1() {
X1<int> x1;
}
+template<typename T>
+struct X2 {
+ void operator()(T = T()); // expected-error{{no matching}}
+};
+
+void test_x2(X2<int> x2i, X2<NotDefaultConstructible> x2n) {
+ x2i();
+ x2i(17);
+ x2n(NotDefaultConstructible(17));
+ x2n(); // expected-note{{in instantiation of default function argument}}
+}
+
// PR5283
namespace PR5283 {
template<typename T> struct A {
@@ -108,3 +120,27 @@ struct D {
};
D::D() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
}
+
+// PR5301
+namespace pr5301 {
+ void f(int, int = 0);
+
+ template <typename T>
+ void g(T, T = 0);
+
+ template <int I>
+ void i(int a = I);
+
+ template <typename T>
+ void h(T t) {
+ f(0);
+ g(1);
+ g(t);
+ i<2>();
+ }
+
+ void test() {
+ h(0);
+ }
+}
+
diff --git a/test/SemaTemplate/enum-argument.cpp b/test/SemaTemplate/enum-argument.cpp
index 101a1d0cd9da..1d782df202e3 100644
--- a/test/SemaTemplate/enum-argument.cpp
+++ b/test/SemaTemplate/enum-argument.cpp
@@ -5,3 +5,19 @@ template <Enum v> struct C {
typedef C<v> Self;
};
template struct C<val>;
+
+template<typename T>
+struct get_size {
+ static const unsigned value = sizeof(T);
+};
+
+template<typename T>
+struct X0 {
+ enum {
+ Val1 = get_size<T>::value,
+ Val2,
+ SumOfValues = Val1 + Val2
+ };
+};
+
+X0<int> x0i;
diff --git a/test/SemaTemplate/example-dynarray.cpp b/test/SemaTemplate/example-dynarray.cpp
index 2b752b4f1f49..6f3e58e32ab6 100644
--- a/test/SemaTemplate/example-dynarray.cpp
+++ b/test/SemaTemplate/example-dynarray.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm-only %s
+// RUN: clang -emit-llvm -S -o %t %s
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
diff --git a/test/SemaTemplate/instantiate-attr.cpp b/test/SemaTemplate/instantiate-attr.cpp
new file mode 100644
index 000000000000..08ba9c3a0cd5
--- /dev/null
+++ b/test/SemaTemplate/instantiate-attr.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template <typename T>
+struct A {
+ char a __attribute__((aligned(16)));
+};
+int a[sizeof(A<int>) == 16 ? 1 : -1];
+
diff --git a/test/SemaTemplate/instantiate-decl-init.cpp b/test/SemaTemplate/instantiate-decl-init.cpp
new file mode 100644
index 000000000000..d957f2de7da5
--- /dev/null
+++ b/test/SemaTemplate/instantiate-decl-init.cpp
@@ -0,0 +1,22 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// PR5426 - the non-dependent obj would be fully processed and wrapped in a
+// CXXConstructExpr at definition time, which would lead to a failure at
+// instantiation time.
+struct arg {
+ arg();
+};
+
+struct oldstylemove {
+ oldstylemove(oldstylemove&);
+ oldstylemove(const arg&);
+};
+
+template <typename T>
+void fn(T t, const arg& arg) {
+ oldstylemove obj(arg);
+}
+
+void test() {
+ fn(1, arg());
+}
diff --git a/test/SemaTemplate/instantiate-member-pointers.cpp b/test/SemaTemplate/instantiate-member-pointers.cpp
index b3ddb3fafa31..d2c9e6b5ed82 100644
--- a/test/SemaTemplate/instantiate-member-pointers.cpp
+++ b/test/SemaTemplate/instantiate-member-pointers.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
struct Y {
int x;
};
@@ -25,3 +24,32 @@ struct X2 {
template struct X2<int, Y>;
template struct X2<int&, Y>; // expected-note{{instantiation}}
template struct X2<const void, Y>; // expected-note{{instantiation}}
+
+template<typename T, typename Class, T Class::*Ptr>
+struct X3 {
+ X3<T, Class, Ptr> &operator=(const T& value) {
+ return *this;
+ }
+};
+
+X3<int, Y, &Y::x> x3;
+
+typedef int Y::*IntMember;
+
+template<IntMember Member>
+struct X4 {
+ X3<int, Y, Member> member;
+
+ int &getMember(Y& y) { return y.*Member; }
+};
+
+int &get_X4(X4<&Y::x> x4, Y& y) {
+ return x4.getMember(y);
+}
+
+template<IntMember Member>
+void accept_X4(X4<Member>);
+
+void test_accept_X4(X4<&Y::x> x4) {
+ accept_X4(x4);
+}
diff --git a/test/SemaTemplate/instantiate-member-template.cpp b/test/SemaTemplate/instantiate-member-template.cpp
index 36f3b6fd490d..95556bcc221b 100644
--- a/test/SemaTemplate/instantiate-member-template.cpp
+++ b/test/SemaTemplate/instantiate-member-template.cpp
@@ -103,3 +103,16 @@ void test_X1(int *ip, int i, double *dp) {
X1<int*>::Inner4<int>::value = 17;
i = X1<int*>::Inner4<int&>::value; // expected-note{{instantiation}}
}
+
+
+template<typename T>
+struct X2 {
+ template<T *Ptr> // expected-error{{pointer to a reference}}
+ struct Inner;
+
+ template<T Value> // expected-error{{cannot have type 'float'}}
+ struct Inner2;
+};
+
+X2<int&> x2a; // expected-note{{instantiation}}
+X2<float> x2b; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/instantiate-overloaded-arrow.cpp b/test/SemaTemplate/instantiate-overloaded-arrow.cpp
new file mode 100644
index 000000000000..7f0ef0c990ad
--- /dev/null
+++ b/test/SemaTemplate/instantiate-overloaded-arrow.cpp
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// PR5488
+
+struct X {
+ int x;
+};
+
+struct Iter {
+ X* operator->();
+};
+
+template <typename T>
+void Foo() {
+ (void)Iter()->x;
+}
+
+void Func() {
+ Foo<int>();
+}
+
diff --git a/test/SemaTemplate/instantiate-template-template-parm.cpp b/test/SemaTemplate/instantiate-template-template-parm.cpp
index b158251915a0..30ba113e20d4 100644
--- a/test/SemaTemplate/instantiate-template-template-parm.cpp
+++ b/test/SemaTemplate/instantiate-template-template-parm.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
template<template<typename T> class MetaFun, typename Value>
struct apply {
typedef typename MetaFun<Value>::type type;
@@ -19,3 +18,29 @@ int i;
apply<add_pointer, int>::type ip = &i;
apply<add_reference, int>::type ir = i;
apply<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a value of type 'int'}}
+
+// Template template parameters
+template<int> struct B; // expected-note{{has a different type 'int'}}
+
+template<typename T,
+ template<T Value> class X> // expected-error{{cannot have type 'float'}} \
+ // expected-note{{with type 'long'}}
+struct X0 { };
+
+X0<int, B> x0b1;
+X0<float, B> x0b2; // expected-note{{while substituting}}
+X0<long, B> x0b3; // expected-error{{template template argument has different template parameters}}
+
+template<template<int V> class TT> // expected-note{{parameter with type 'int'}}
+struct X1 { };
+
+template<typename T, template<T V> class TT>
+struct X2 {
+ X1<TT> x1; // expected-error{{has different template parameters}}
+};
+
+template<int V> struct X3i { };
+template<long V> struct X3l { }; // expected-note{{different type 'long'}}
+
+X2<int, X3i> x2okay;
+X2<long, X3l> x2bad; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/instantiate-using-decl.cpp b/test/SemaTemplate/instantiate-using-decl.cpp
index fd9010fa4bbb..a1cf355c890e 100644
--- a/test/SemaTemplate/instantiate-using-decl.cpp
+++ b/test/SemaTemplate/instantiate-using-decl.cpp
@@ -1,5 +1,7 @@
// RUN: clang-cc -fsyntax-only -verify %s
+namespace N { }
+
template<typename T>
struct A {
void f();
@@ -10,6 +12,7 @@ struct B : A<T> {
using A<T>::f;
void g() {
+ using namespace N;
f();
}
};
diff --git a/test/SemaTemplate/instantiation-default-2.cpp b/test/SemaTemplate/instantiation-default-2.cpp
index 740832c5ba39..4d9a0e2717bf 100644
--- a/test/SemaTemplate/instantiation-default-2.cpp
+++ b/test/SemaTemplate/instantiation-default-2.cpp
@@ -15,4 +15,4 @@ Constant<float (*)(int, double), &f> *c5;
Constant<float (*)(int, int), f> *c6; // expected-error{{non-type template argument of type 'float (*)(int, double)' cannot be converted to a value of type 'float (*)(int, int)'}}
-Constant<float, 0> *c7; // expected-note{{in instantiation of default argument for 'Constant<float>' required here}}
+Constant<float, 0> *c7; // expected-note{{while substituting}}
diff --git a/test/SemaTemplate/member-function-template.cpp b/test/SemaTemplate/member-function-template.cpp
index 83bf16c69004..1d46d31e35d3 100644
--- a/test/SemaTemplate/member-function-template.cpp
+++ b/test/SemaTemplate/member-function-template.cpp
@@ -49,3 +49,27 @@ void test_X_f0_explicit(X x, int i, long l) {
// PR4608
class A { template <class x> x a(x z) { return z+y; } int y; };
+// PR5419
+struct Functor {
+ template <typename T>
+ bool operator()(const T& v) const {
+ return true;
+ }
+};
+
+void test_Functor(Functor f) {
+ f(1);
+}
+
+// Instantiation on ->
+template<typename T>
+struct X1 {
+ template<typename U> U& get();
+};
+
+template<typename T> struct X2; // expected-note{{here}}
+
+void test_incomplete_access(X1<int> *x1, X2<int> *x2) {
+ float &fr = x1->get<float>();
+ (void)x2->get<float>(); // expected-error{{implicit instantiation of undefined template}}
+}
diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp
index 1bdc7a89d4e8..e936640f5e3e 100644
--- a/test/SemaTemplate/nested-name-spec-template.cpp
+++ b/test/SemaTemplate/nested-name-spec-template.cpp
@@ -28,11 +28,8 @@ N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; }
::N::M::Promote<int>::type *ret_intptr6(int* ip) { return ip; }
-N::M::template; // expected-error{{expected template name after 'template' keyword in nested name specifier}} \
- // expected-error{{expected unqualified-id}}
-
-N::M::template Promote; // expected-error{{expected '<' after 'template Promote' in nested name specifier}} \
-// expected-error{{C++ requires a type specifier for all declarations}}
+N::M::template; // expected-error{{expected unqualified-id}}
+N::M::template Promote; // expected-error{{expected unqualified-id}}
namespace N {
template<typename T> struct A;
@@ -49,13 +46,9 @@ struct ::N::A<int>::X {
int foo;
};
-#if 0
-// FIXME: the following crashes the parser, because Sema has no way to
-// communicate that the "dependent" template-name N::template B doesn't
-// actually refer to a template.
template<typename T>
struct TestA {
- typedef typename N::template B<T>::type type; // xpected-error{{'B' following the 'template' keyword does not refer to a template}}
- // FIXME: should show what B *does* refer to.
+ typedef typename N::template B<T>::type type; // expected-error{{'B' following the 'template' keyword does not refer to a template}} \
+ // expected-error{{identifier or template-id}} \
+ // expected-error{{expected member name}}
};
-#endif
diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp
index 4d948184cee9..e18329c145d0 100644
--- a/test/SemaTemplate/nested-template.cpp
+++ b/test/SemaTemplate/nested-template.cpp
@@ -108,3 +108,21 @@ struct X1 {
template<typename, bool = false> struct B { };
};
template struct X1<int>::B<bool>;
+
+// Template template parameters
+template<typename T>
+struct X2 {
+ template<template<class U, T Value> class> // expected-error{{cannot have type 'float'}} \
+ // expected-note{{previous non-type template}}
+ struct Inner { };
+};
+
+template<typename T,
+ int Value> // expected-note{{template non-type parameter}}
+ struct X2_arg;
+
+X2<int>::Inner<X2_arg> x2i1;
+X2<float> x2a; // expected-note{{instantiation}}
+X2<long>::Inner<X2_arg> x2i3; // expected-error{{template template argument has different}}
+
+
diff --git a/test/SemaTemplate/operator-template.cpp b/test/SemaTemplate/operator-template.cpp
index 7039e0ec83de..dc44d04b6882 100644
--- a/test/SemaTemplate/operator-template.cpp
+++ b/test/SemaTemplate/operator-template.cpp
@@ -11,6 +11,6 @@ int a0(A<int> x) { return x == 1; }
template<class X>struct B{typedef X Y;};
template<class X>bool operator==(B<X>*,typename B<X>::Y); // \
expected-error{{overloaded 'operator==' must have at least one parameter of class or enumeration type}} \
-expected-note{{in instantiation of member function}}
+expected-note{{in instantiation of function template specialization}}
int a(B<int> x) { return operator==(&x,1); }
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index a6611582f170..bde92be93dfb 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -10,8 +10,7 @@ A<int> *a2; // expected-error{{template argument for non-type template parameter
A<1 >> 2> *a3; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++0x}}
// C++ [temp.arg.nontype]p5:
-A<A> *a4; // expected-error{{must have an integral or enumeration type}} \
- // FIXME: the error message above is a bit lame
+A<A> *a4; // expected-error{{must be an expression}}
enum E { Enumerator = 17 };
A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}}
diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp
index f2ee66b3f731..ada244bb5de6 100644
--- a/test/SemaTemplate/temp_arg_template.cpp
+++ b/test/SemaTemplate/temp_arg_template.cpp
@@ -26,12 +26,9 @@ B<X> *a6; // expected-error{{template template argument has different template p
C<Y> *a7;
C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
-template<typename T> void f(int); // expected-note{{function template}}
+template<typename T> void f(int);
-// FIXME: we're right to provide an error message, but it should say
-// that we need a class template. We won't get this right until name
-// lookup of 'f' returns a TemplateDecl.
-A<f> *a9; // expected-error{{template argument does not refer to}}
+A<f> *a9; // expected-error{{must be a class template}}
// FIXME: The code below is ill-formed, because of the evil digraph '<:'.
// We should provide a much better error message than we currently do.
diff --git a/test/SemaTemplate/value-dependent-null-pointer-constant.cpp b/test/SemaTemplate/value-dependent-null-pointer-constant.cpp
index 8bde1277edd5..110c380c9aa2 100644
--- a/test/SemaTemplate/value-dependent-null-pointer-constant.cpp
+++ b/test/SemaTemplate/value-dependent-null-pointer-constant.cpp
@@ -26,4 +26,4 @@ struct A { };
template <typename T> void f(T *t)
{
(void)static_cast<void*>(static_cast<A*>(t));
-} \ No newline at end of file
+}
diff --git a/test/lit.cfg b/test/lit.cfg
index 9b274fed30b5..6fa6742a4ac5 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -13,8 +13,7 @@ config.name = 'Clang'
# For now we require '&&' between commands, until they get globally killed and
# the test runner updated.
execute_external = platform.system() != 'Windows'
-config.test_format = lit.formats.ShTest(execute_external,
- require_and_and = True)
+config.test_format = lit.formats.ShTest(execute_external)
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.c', '.cpp', '.m', '.mm']
@@ -66,8 +65,9 @@ if config.test_exec_root is None:
#
# FIXME: I debated (i.e., wrote and threw away) adding logic to
# automagically generate the lit.site.cfg if we are in some kind of fresh
- # build situation. This means knowing how to invoke the build system
- # though, and I decided it was too much magic.
+ # build situation. This means knowing how to invoke the build system though,
+ # and I decided it was too much magic. We should solve this by just having
+ # the .cfg files generated during the configuration step.
llvm_config = lit.util.which('llvm-config', config.environment['PATH'])
if not llvm_config:
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index c88c90b7c5df..0d452ef6b55a 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -7,5 +7,14 @@ config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
config.clang_obj_root = "@CLANG_BINARY_DIR@"
config.target_triple = "@TARGET_TRIPLE@"
+# Support substitution of the tools and libs dirs with user parameters. This is
+# used when we can't determine the tool dir at configuration time.
+try:
+ config.llvm_tools_dir = config.llvm_tools_dir % lit.params
+ config.llvm_libs_dir = config.llvm_libs_dir % lit.params
+except KeyError,e:
+ key, = e.args
+ lit.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
+
# Let the main config do the real work.
lit.load_config(config, "@CLANG_SOURCE_DIR@/test/lit.cfg")
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 4798e2832822..ebdba29d92fb 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -16,12 +16,15 @@
#include "clang/Index/Indexer.h"
#include "clang/Index/ASTLocation.h"
#include "clang/Index/Utils.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/ASTUnit.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -31,6 +34,7 @@
#include <cstdio>
#include <vector>
+#include <sstream>
#ifdef LLVM_ON_WIN32
#define WIN32_LEAN_AND_MEAN
@@ -137,8 +141,25 @@ public:
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
Visit(*I);
}
- void VisitTypedefDecl(TypedefDecl *ND) {
- Call(CXCursor_TypedefDecl, ND);
+
+ void VisitFunctionDecl(FunctionDecl *ND) {
+ Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
+ : CXCursor_FunctionDecl, ND);
+ }
+ void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
+ Call(CXCursor_ObjCCategoryDecl, ND);
+ }
+ void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
+ Call(CXCursor_ObjCCategoryDefn, ND);
+ }
+ void VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
+ Call(CXCursor_ObjCClassDefn, ND);
+ }
+ void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
+ Call(CXCursor_ObjCInterfaceDecl, ND);
+ }
+ void VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
+ Call(CXCursor_ObjCProtocolDecl, ND);
}
void VisitTagDecl(TagDecl *ND) {
switch (ND->getTagKind()) {
@@ -156,29 +177,14 @@ public:
break;
}
}
+ void VisitTypedefDecl(TypedefDecl *ND) {
+ Call(CXCursor_TypedefDecl, ND);
+ }
void VisitVarDecl(VarDecl *ND) {
Call(CXCursor_VarDecl, ND);
- }
- void VisitFunctionDecl(FunctionDecl *ND) {
- Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
- : CXCursor_FunctionDecl, ND);
- }
- void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
- Call(CXCursor_ObjCInterfaceDecl, ND);
- }
- void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
- Call(CXCursor_ObjCCategoryDecl, ND);
- }
- void VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
- Call(CXCursor_ObjCProtocolDecl, ND);
- }
- void VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
- Call(CXCursor_ObjCClassDefn, ND);
- }
- void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
- Call(CXCursor_ObjCCategoryDefn, ND);
- }
+ }
};
+
// Declaration visitor.
class CDeclVisitor : public DeclVisitor<CDeclVisitor> {
@@ -327,6 +333,11 @@ const llvm::sys::Path& CIndexer::getClangPath() {
GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
llvm::sys::Path CIndexPath(path);
+
+ CIndexPath.eraseComponent();
+ CIndexPath.appendComponent("clang");
+ CIndexPath.appendSuffix("exe");
+ CIndexPath.makeAbsolute();
#else
// This silly cast below avoids a C++ warning.
Dl_info info;
@@ -334,13 +345,13 @@ const llvm::sys::Path& CIndexer::getClangPath() {
assert(0 && "Call to dladdr() failed");
llvm::sys::Path CIndexPath(info.dli_fname);
-#endif
// We now have the CIndex directory, locate clang relative to it.
CIndexPath.eraseComponent();
CIndexPath.eraseComponent();
CIndexPath.appendComponent("bin");
CIndexPath.appendComponent("clang");
+#endif
// Cache our result.
ClangPath = CIndexPath;
@@ -349,6 +360,82 @@ const llvm::sys::Path& CIndexer::getClangPath() {
}
+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.
+ }
+}
+
+static CXString createCXString(const char *String, bool DupString = false) {
+ CXString Str;
+ if (DupString) {
+ Str.Spelling = strdup(String);
+ Str.MustFreeString = 1;
+ } else {
+ Str.Spelling = String;
+ Str.MustFreeString = 0;
+ }
+ return Str;
+}
+
extern "C" {
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
@@ -384,7 +471,7 @@ CXTranslationUnit clang_createTranslationUnit(
CXXIdx->getOnlyLocalDecls(),
/* UseBumpAllocator = */ true);
- if (!ErrMsg.empty())
+ if (CXXIdx->getDisplayDiagnostics() && !ErrMsg.empty())
llvm::errs() << "clang_createTranslationUnit: " << ErrMsg << '\n';
return TU;
@@ -447,7 +534,7 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile(
/* redirects */ !CXXIdx->getDisplayDiagnostics() ? &Redirects[0] : NULL,
/* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg);
- if (!ErrMsg.empty()) {
+ if (CXXIdx->getDisplayDiagnostics() && !ErrMsg.empty()) {
llvm::errs() << "clang_createTranslationUnitFromSourceFile: " << ErrMsg
<< '\n' << "Arguments: \n";
for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
@@ -473,11 +560,11 @@ void clang_disposeTranslationUnit(
delete static_cast<ASTUnit *>(CTUnit);
}
-const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
+CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
{
assert(CTUnit && "Passed null CXTranslationUnit");
ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
- return CXXUnit->getOriginalSourceFileName().c_str();
+ return createCXString(CXXUnit->getOriginalSourceFileName().c_str(), true);
}
void clang_loadTranslationUnit(CXTranslationUnit CTUnit,
@@ -542,24 +629,24 @@ CXEntity clang_getEntityFromDecl(CXDecl)
{
return 0;
}
-const char *clang_getDeclSpelling(CXDecl AnonDecl)
+CXString clang_getDeclSpelling(CXDecl AnonDecl)
{
assert(AnonDecl && "Passed null CXDecl");
NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
-
- if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) {
- return OMD->getSelector().getAsString().c_str();
- }
+
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ return 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 CIMP->getIdentifier()->getNameStart();
-
+ return createCXString(CIMP->getIdentifier()->getNameStart());
+
if (ND->getIdentifier())
- return ND->getIdentifier()->getNameStart();
- else
- return "";
+ return createCXString(ND->getIdentifier()->getNameStart());
+
+ return createCXString("");
}
unsigned clang_getDeclLine(CXDecl AnonDecl)
@@ -617,36 +704,38 @@ time_t clang_getFileTime(CXFile SFile) {
return FEnt->getModificationTime();
}
-const char *clang_getCursorSpelling(CXCursor C)
+CXString clang_getCursorSpelling(CXCursor C)
{
assert(C.decl && "CXCursor has null decl");
NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
-
+
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 OID->getSuperClass()->getIdentifier()->getNameStart();
+ return createCXString(OID->getSuperClass()->getIdentifier()
+ ->getNameStart());
}
case CXCursor_ObjCClassRef: {
- if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND)) {
- return OID->getIdentifier()->getNameStart();
- }
- ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing category decl");
- return OID->getClassInterface()->getIdentifier()->getNameStart();
+ if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND))
+ return createCXString(OID->getIdentifier()->getNameStart());
+
+ ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(ND);
+ assert(OCD && "clang_getCursorLine(): Missing category decl");
+ return createCXString(OCD->getClassInterface()->getIdentifier()
+ ->getNameStart());
}
case CXCursor_ObjCProtocolRef: {
ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
assert(OID && "clang_getCursorLine(): Missing protocol decl");
- return OID->getIdentifier()->getNameStart();
+ return 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 OME->getSelector().getAsString().c_str();
+ return createCXString(OME->getSelector().getAsString().c_str(), true);
}
case CXCursor_VarRef:
case CXCursor_FunctionRef:
@@ -654,10 +743,10 @@ const char *clang_getCursorSpelling(CXCursor C)
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
static_cast<Stmt *>(C.stmt));
assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
- return DRE->getDecl()->getIdentifier()->getNameStart();
+ return createCXString(DRE->getDecl()->getIdentifier()->getNameStart());
}
default:
- return "<not implemented>";
+ return createCXString("<not implemented>");
}
}
return clang_getDeclSpelling(C.decl);
@@ -786,6 +875,18 @@ CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,
return C;
}
+CXCursor clang_getNullCursor(void) {
+ CXCursor C;
+ C.kind = CXCursor_InvalidFile;
+ C.decl = NULL;
+ C.stmt = NULL;
+ return C;
+}
+
+unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
+ return X.kind == Y.kind && X.decl == Y.decl && X.stmt == Y.stmt;
+}
+
CXCursor clang_getCursorFromDecl(CXDecl AnonDecl)
{
assert(AnonDecl && "Passed null CXDecl");
@@ -856,71 +957,6 @@ CXDecl clang_getCursorDecl(CXCursor C)
return 0;
}
-
-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.
- }
-}
-
unsigned clang_getCursorLine(CXCursor C)
{
assert(C.decl && "CXCursor has null decl");
@@ -931,6 +967,17 @@ unsigned clang_getCursorLine(CXCursor C)
return SourceMgr.getSpellingLineNumber(SLoc);
}
+// Access string.
+const char *clang_getCString(CXString string) {
+ return string.Spelling;
+}
+
+// Free CXString.
+void clang_disposeString(CXString string) {
+ if (string.MustFreeString)
+ free((void*)string.Spelling);
+}
+
unsigned clang_getCursorColumn(CXCursor C)
{
assert(C.decl && "CXCursor has null decl");
@@ -947,8 +994,11 @@ const char *clang_getCursorSource(CXCursor C)
SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
- if (SLoc.isFileID())
- return SourceMgr.getBufferName(SLoc);
+
+ if (SLoc.isFileID()) {
+ const char *bufferName = SourceMgr.getBufferName(SLoc);
+ return bufferName[0] == '<' ? NULL : bufferName;
+ }
// Retrieve the file in which the macro was instantiated, then provide that
// buffer name.
@@ -993,5 +1043,318 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C,
*endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
}
+enum CXCompletionChunkKind
+clang_getCompletionChunkKind(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return CXCompletionChunk_Text;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ return CXCompletionChunk_TypedText;
+ case CodeCompletionString::CK_Text:
+ return CXCompletionChunk_Text;
+ case CodeCompletionString::CK_Optional:
+ return CXCompletionChunk_Optional;
+ case CodeCompletionString::CK_Placeholder:
+ return CXCompletionChunk_Placeholder;
+ case CodeCompletionString::CK_Informative:
+ return CXCompletionChunk_Informative;
+ case CodeCompletionString::CK_CurrentParameter:
+ return CXCompletionChunk_CurrentParameter;
+ case CodeCompletionString::CK_LeftParen:
+ return CXCompletionChunk_LeftParen;
+ case CodeCompletionString::CK_RightParen:
+ return CXCompletionChunk_RightParen;
+ case CodeCompletionString::CK_LeftBracket:
+ return CXCompletionChunk_LeftBracket;
+ case CodeCompletionString::CK_RightBracket:
+ return CXCompletionChunk_RightBracket;
+ case CodeCompletionString::CK_LeftBrace:
+ return CXCompletionChunk_LeftBrace;
+ case CodeCompletionString::CK_RightBrace:
+ return CXCompletionChunk_RightBrace;
+ case CodeCompletionString::CK_LeftAngle:
+ return CXCompletionChunk_LeftAngle;
+ case CodeCompletionString::CK_RightAngle:
+ return CXCompletionChunk_RightAngle;
+ case CodeCompletionString::CK_Comma:
+ return CXCompletionChunk_Comma;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return CXCompletionChunk_Text;
+}
+
+const char *clang_getCompletionChunkText(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return 0;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ return (*CCStr)[chunk_number].Text;
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return 0;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return 0;
+}
+
+CXCompletionString
+clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return 0;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ return 0;
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return (*CCStr)[chunk_number].Optional;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return 0;
+}
+
+unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr? CCStr->size() : 0;
+}
+static CXCursorKind parseResultKind(llvm::StringRef Str) {
+ return llvm::StringSwitch<CXCursorKind>(Str)
+ .Case("Typedef", CXCursor_TypedefDecl)
+ .Case("Struct", CXCursor_StructDecl)
+ .Case("Union", CXCursor_UnionDecl)
+ .Case("Class", CXCursor_ClassDecl)
+ .Case("Enum", CXCursor_EnumDecl)
+ .Case("Field", CXCursor_FieldDecl)
+ .Case("EnumConstant", CXCursor_EnumConstantDecl)
+ .Case("Function", CXCursor_FunctionDecl)
+ // FIXME: Hacks here to make C++ member functions look like C functions
+ .Case("CXXMethod", CXCursor_FunctionDecl)
+ .Case("CXXConstructor", CXCursor_FunctionDecl)
+ .Case("CXXDestructor", CXCursor_FunctionDecl)
+ .Case("CXXConversion", CXCursor_FunctionDecl)
+ .Case("Var", CXCursor_VarDecl)
+ .Case("ParmVar", CXCursor_ParmDecl)
+ .Case("ObjCInterface", CXCursor_ObjCInterfaceDecl)
+ .Case("ObjCCategory", CXCursor_ObjCCategoryDecl)
+ .Case("ObjCProtocol", CXCursor_ObjCProtocolDecl)
+ .Case("ObjCProperty", CXCursor_ObjCPropertyDecl)
+ .Case("ObjCIvar", CXCursor_ObjCIvarDecl)
+ .Case("ObjCInstanceMethod", CXCursor_ObjCInstanceMethodDecl)
+ .Case("ObjCClassMethod", CXCursor_ObjCClassMethodDecl)
+ .Default(CXCursor_NotImplemented);
+}
+
+void clang_codeComplete(CXIndex CIdx,
+ const char *source_filename,
+ int num_command_line_args,
+ const char **command_line_args,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column,
+ CXCompletionIterator completion_iterator,
+ CXClientData client_data) {
+ // The indexer, which is mainly used to determine where diagnostics go.
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+
+ // Build up the arguments for invoking 'clang'.
+ std::vector<const char *> argv;
+
+ // First add the complete path to the 'clang' executable.
+ llvm::sys::Path ClangPath = CXXIdx->getClangPath();
+ argv.push_back(ClangPath.c_str());
+
+ // Add the '-fsyntax-only' argument so that we only perform a basic
+ // syntax check of the code.
+ argv.push_back("-fsyntax-only");
+
+ // Add the appropriate '-code-completion-at=file:line:column' argument
+ // to perform code completion, with an "-Xclang" preceding it.
+ std::string code_complete_at;
+ code_complete_at += "-code-completion-at=";
+ code_complete_at += complete_filename;
+ code_complete_at += ":";
+ code_complete_at += llvm::utostr(complete_line);
+ code_complete_at += ":";
+ code_complete_at += llvm::utostr(complete_column);
+ argv.push_back("-Xclang");
+ argv.push_back(code_complete_at.c_str());
+ argv.push_back("-Xclang");
+ argv.push_back("-code-completion-debug-printer=0");
+
+ // Add the source file name (FIXME: later, we'll want to build temporary
+ // file from the buffer, or just feed the source text via standard input).
+ if (source_filename)
+ argv.push_back(source_filename);
+
+ // 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]) {
+ if (strcmp(arg, "-o") == 0) {
+ ++i; // Also skip the matching argument.
+ continue;
+ }
+ if (strcmp(arg, "-emit-ast") == 0 ||
+ strcmp(arg, "-c") == 0 ||
+ strcmp(arg, "-fsyntax-only") == 0) {
+ continue;
+ }
+
+ // Keep the argument.
+ argv.push_back(arg);
+ }
+
+ // Add the null terminator.
+ argv.push_back(NULL);
+
+ // Generate a temporary name for the AST file.
+ char tmpFile[L_tmpnam];
+ char *tmpFileName = tmpnam(tmpFile);
+ llvm::sys::Path ResultsFile(tmpFileName);
+
+ // Invoke 'clang'.
+ llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
+ // on Unix or NUL (Windows).
+ std::string ErrMsg;
+ const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile, &DevNull, 0 };
+ llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
+ /* redirects */ &Redirects[0],
+ /* secondsToWait */ 0,
+ /* memoryLimits */ 0, &ErrMsg);
+
+ if (CXXIdx->getDisplayDiagnostics() && !ErrMsg.empty()) {
+ llvm::errs() << "clang_codeComplete: " << ErrMsg
+ << '\n' << "Arguments: \n";
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I!=E; ++I) {
+ if (*I)
+ llvm::errs() << ' ' << *I << '\n';
+ }
+ llvm::errs() << '\n';
+ }
+
+ // Parse the resulting source file to find code-completion results.
+ using llvm::MemoryBuffer;
+ using llvm::StringRef;
+ if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
+ StringRef Buffer = F->getBuffer();
+ do {
+ StringRef::size_type CompletionIdx = Buffer.find("COMPLETION:");
+ StringRef::size_type OverloadIdx = Buffer.find("OVERLOAD:");
+ if (CompletionIdx == StringRef::npos && OverloadIdx == StringRef::npos)
+ break;
+
+ if (OverloadIdx < CompletionIdx) {
+ // Parse an overload result.
+ Buffer = Buffer.substr(OverloadIdx);
+
+ // Skip past the OVERLOAD:
+ Buffer = Buffer.substr(Buffer.find(':') + 1);
+
+ // Find the entire completion string.
+ StringRef::size_type EOL = Buffer.find_first_of("\n\r");
+ if (EOL == StringRef::npos)
+ continue;
+
+ StringRef Line = Buffer.substr(0, EOL);
+ Buffer = Buffer.substr(EOL + 1);
+ CodeCompletionString *CCStr = CodeCompletionString::Deserialize(Line);
+ if (!CCStr || CCStr->empty())
+ continue;
+
+ // Vend the code-completion result to the caller.
+ CXCompletionResult Result;
+ Result.CursorKind = CXCursor_NotImplemented;
+ Result.CompletionString = CCStr;
+ if (completion_iterator)
+ completion_iterator(&Result, client_data);
+ delete CCStr;
+
+ continue;
+ }
+
+ // Parse a completion result.
+ Buffer = Buffer.substr(CompletionIdx);
+
+ // Skip past the COMPLETION:
+ Buffer = Buffer.substr(Buffer.find(':') + 1);
+
+ // Get the rank
+ unsigned Rank = 0;
+ StringRef::size_type AfterRank = Buffer.find(':');
+ Buffer.substr(0, AfterRank).getAsInteger(10, Rank);
+ Buffer = Buffer.substr(AfterRank + 1);
+
+ // Get the kind of result.
+ StringRef::size_type AfterKind = Buffer.find(':');
+ StringRef Kind = Buffer.substr(0, AfterKind);
+ Buffer = Buffer.substr(AfterKind + 1);
+
+ // Skip over any whitespace.
+ Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
+
+ // Find the entire completion string.
+ StringRef::size_type EOL = Buffer.find_first_of("\n\r");
+ if (EOL == StringRef::npos)
+ continue;
+
+ StringRef Line = Buffer.substr(0, EOL);
+ Buffer = Buffer.substr(EOL + 1);
+ CodeCompletionString *CCStr = CodeCompletionString::Deserialize(Line);
+ if (!CCStr || CCStr->empty())
+ continue;
+
+ // Vend the code-completion result to the caller.
+ CXCompletionResult Result;
+ Result.CursorKind = parseResultKind(Kind);
+ Result.CompletionString = CCStr;
+ if (completion_iterator)
+ completion_iterator(&Result, client_data);
+ delete CCStr;
+ } while (true);
+ delete F;
+ }
+
+ ResultsFile.eraseFromDisk();
+}
+
} // end extern "C"
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index 5f461d8ef600..2892ce50e70d 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -1,8 +1,14 @@
+_clang_codeComplete
_clang_createIndex
_clang_createTranslationUnit
_clang_createTranslationUnitFromSourceFile
_clang_disposeIndex
+_clang_disposeString
_clang_disposeTranslationUnit
+_clang_equalCursors
+_clang_getCompletionChunkCompletionString
+_clang_getCompletionChunkKind
+_clang_getCompletionChunkText
_clang_getCursor
_clang_getCursorColumn
_clang_getCursorDecl
@@ -13,6 +19,7 @@ _clang_getCursorLine
_clang_getCursorSource
_clang_getCursorSourceFile
_clang_getCursorSpelling
+_clang_getCString
_clang_getDeclColumn
_clang_getDeclLine
_clang_getDeclSource
@@ -24,6 +31,8 @@ _clang_getEntity
_clang_getEntityFromDecl
_clang_getFileName
_clang_getFileTime
+_clang_getNullCursor
+_clang_getNumCompletionChunks
_clang_getTranslationUnitSpelling
_clang_getURI
_clang_isDeclaration
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index dd0eeea9443a..69de8a1acffb 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -3,7 +3,7 @@ set(SHARED_LIBRARY TRUE)
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
- clangFrontend clangIndex clangSema clangAST clangLex clangBasic)
+ clangFrontend clangIndex clangSema clangAnalysis clangAST clangParse clangLex clangBasic)
set( LLVM_LINK_COMPONENTS
MC
diff --git a/tools/CIndex/Makefile b/tools/CIndex/Makefile
index a9ff394f3399..a34f68ba115b 100644
--- a/tools/CIndex/Makefile
+++ b/tools/CIndex/Makefile
@@ -22,7 +22,7 @@ LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
LINK_COMPONENTS := MC support
-USEDLIBS = clangFrontend.a clangIndex.a clangSema.a clangAST.a clangLex.a clangBasic.a
+USEDLIBS = clangFrontend.a clangIndex.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 222512af1546..8cded43151c8 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,9 +1,5 @@
add_subdirectory(clang-cc)
add_subdirectory(driver)
add_subdirectory(index-test)
-option(CLANG_BUILD_EXPERIMENTAL "Build experimenal Clang tools" OFF)
-if (CLANG_BUILD_EXPERIMENTAL)
- add_subdirectory(wpa)
-endif ()
add_subdirectory(CIndex)
add_subdirectory(c-index-test)
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 8791ee20a583..289dee962987 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1,9 +1,14 @@
/* c-index-test.c */
#include "clang-c/Index.h"
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+/******************************************************************************/
+/* Utility functions. */
+/******************************************************************************/
+
#ifdef _MSC_VER
char *basename(const char* path)
{
@@ -22,13 +27,32 @@ char *basename(const char* path)
extern char *basename(const char *);
#endif
+static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
+ CXTranslationUnit *TU) {
+
+ *TU = clang_createTranslationUnit(Idx, file);
+ if (!TU) {
+ fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
+ return 0;
+ }
+ return 1;
+}
+
+
+/******************************************************************************/
+/* Pretty-printing. */
+/******************************************************************************/
+
static void PrintCursor(CXCursor Cursor) {
if (clang_isInvalid(Cursor.kind))
- printf("Invalid Cursor => %s\n", clang_getCursorKindSpelling(Cursor.kind));
+ printf("Invalid Cursor => %s", clang_getCursorKindSpelling(Cursor.kind));
else {
CXDecl DeclReferenced;
+ CXString string;
+ string = clang_getCursorSpelling(Cursor);
printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind),
- clang_getCursorSpelling(Cursor));
+ clang_getCString(string));
+ clang_disposeString(string);
DeclReferenced = clang_getCursorDecl(Cursor);
if (DeclReferenced)
printf(":%d:%d", clang_getDeclLine(DeclReferenced),
@@ -36,25 +60,43 @@ static void PrintCursor(CXCursor Cursor) {
}
}
+static const char* GetCursorSource(CXCursor Cursor) {
+ const char *source = clang_getCursorSource(Cursor);
+ if (!source)
+ return "<invalid loc>";
+ return basename(source);
+}
+
+/******************************************************************************/
+/* Logic for testing clang_loadTranslationUnit(). */
+/******************************************************************************/
+
static void DeclVisitor(CXDecl Dcl, CXCursor Cursor, CXClientData Filter)
{
if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
- printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
+ CXString string;
+ printf("// CHECK: %s:%d:%d: ", GetCursorSource(Cursor),
clang_getCursorLine(Cursor),
clang_getCursorColumn(Cursor));
PrintCursor(Cursor);
- printf(" [Context=%s]\n", clang_getDeclSpelling(Dcl));
+ string = clang_getDeclSpelling(Dcl);
+ printf(" [Context=%s]\n", clang_getCString(string));
+ clang_disposeString(string);
}
}
static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
CXClientData Filter)
{
if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
- printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
+ CXString string;
+ printf("// CHECK: %s:%d:%d: ", GetCursorSource(Cursor),
clang_getCursorLine(Cursor),
clang_getCursorColumn(Cursor));
PrintCursor(Cursor);
- printf(" [Context=%s]\n", basename(clang_getTranslationUnitSpelling(Unit)));
+ string = clang_getTranslationUnitSpelling(Unit);
+ printf(" [Context=%s]\n",
+ basename(clang_getCString(string)));
+ clang_disposeString(string);
clang_loadDeclaration(Cursor.decl, DeclVisitor, 0);
@@ -82,10 +124,13 @@ static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
if (Ref.kind == CXCursor_NoDeclFound) {
/* Nothing found here; that's fine. */
} else if (Ref.kind != CXCursor_FunctionDecl) {
- printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Ref)),
- curLine, curColumn);
+ CXString string;
+ printf("// CHECK: %s:%d:%d: ", GetCursorSource(Ref),
+ curLine, curColumn);
PrintCursor(Ref);
- printf(" [Context:%s]\n", clang_getDeclSpelling(Ref.decl));
+ string = clang_getDeclSpelling(Ref.decl);
+ printf(" [Context:%s]\n", clang_getCString(string));
+ clang_disposeString(string);
}
startBuf++;
}
@@ -94,43 +139,280 @@ static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
}
}
-/*
- * First sign of life:-)
- */
-int main(int argc, char **argv) {
- if (argc != 3) {
- printf("Incorrect usage of c-index-test (requires 3 arguments)\n");
- return 0;
- }
- {
+int perform_test_load_tu(const char *file, const char *filter) {
CXIndex Idx;
CXTranslationUnit TU;
enum CXCursorKind K = CXCursor_NotImplemented;
-
- Idx = clang_createIndex(/* excludeDeclsFromPCH */ !strcmp(argv[2], "local") ? 1 : 0,
+ enum CXCursorKind *ck = &K;
+ Idx = clang_createIndex(/* excludeDeclsFromPCH */
+ !strcmp(filter, "local") ? 1 : 0,
/* displayDiagnostics */ 1);
- TU = clang_createTranslationUnit(Idx, argv[1]);
+ if (!CreateTranslationUnit(Idx, file, &TU))
+ return 1;
+
+ /* Perform some simple filtering. */
+ if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
+ else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
+ else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl;
+ else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl;
+ else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl;
+ else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl;
+ else {
+ fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter);
+ return 1;
+ }
+
+ clang_loadTranslationUnit(TU, TranslationUnitVisitor, ck);
+ clang_disposeTranslationUnit(TU);
+ return 0;
+}
- if (!TU) {
- fprintf(stderr, "Unable to load translation unit!\n");
+/******************************************************************************/
+/* Logic for testing clang_getCursor(). */
+/******************************************************************************/
+
+static void print_cursor_file_scan(CXCursor cursor,
+ unsigned start_line, unsigned start_col,
+ unsigned end_line, unsigned end_col,
+ const char *prefix) {
+ printf("// CHECK");
+ if (prefix)
+ printf("-%s", prefix);
+ printf("{start_line=%d start_col=%d end_line=%d end_col=%d} ",
+ start_line, start_col, end_line, end_col);
+ PrintCursor(cursor);
+ printf("\n");
+}
+
+static int perform_file_scan(const char *ast_file, const char *source_file,
+ const char *prefix) {
+ CXIndex Idx;
+ CXTranslationUnit TU;
+ FILE *fp;
+ unsigned line;
+ CXCursor prevCursor;
+ unsigned printed;
+ unsigned start_line, start_col, last_line, last_col;
+ size_t i;
+
+ if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
+ /* displayDiagnostics */ 1))) {
+ fprintf(stderr, "Could not create Index\n");
+ return 1;
+ }
+
+ if (!CreateTranslationUnit(Idx, ast_file, &TU))
+ return 1;
+
+ if ((fp = fopen(source_file, "r")) == NULL) {
+ fprintf(stderr, "Could not open '%s'\n", source_file);
+ return 1;
+ }
+
+ line = 0;
+ prevCursor = clang_getNullCursor();
+ printed = 0;
+ start_line = last_line = 1;
+ start_col = last_col = 1;
+
+ while (!feof(fp)) {
+ size_t len = 0;
+ int c;
+
+ while ((c = fgetc(fp)) != EOF) {
+ len++;
+ if (c == '\n')
+ break;
+ }
+
+ ++line;
+
+ for (i = 0; i < len ; ++i) {
+ CXCursor cursor;
+ cursor = clang_getCursor(TU, source_file, line, i+1);
+
+ if (!clang_equalCursors(cursor, prevCursor) &&
+ prevCursor.kind != CXCursor_InvalidFile) {
+ print_cursor_file_scan(prevCursor, start_line, start_col,
+ last_line, last_col, prefix);
+ printed = 1;
+ start_line = line;
+ start_col = (unsigned) i+1;
+ }
+ else {
+ printed = 0;
+ }
+
+ prevCursor = cursor;
+ last_line = line;
+ last_col = (unsigned) i+1;
+ }
+ }
+
+ if (!printed && prevCursor.kind != CXCursor_InvalidFile) {
+ print_cursor_file_scan(prevCursor, start_line, start_col,
+ last_line, last_col, prefix);
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+/******************************************************************************/
+/* Logic for testing clang_codeComplete(). */
+/******************************************************************************/
+
+/* Parse file:line:column from the input string. Returns 0 on success, non-zero
+ on failure. If successful, the pointer *filename will contain newly-allocated
+ memory (that will be owned by the caller) to store the file name. */
+int parse_file_line_column(const char *input, char **filename, unsigned *line,
+ unsigned *column) {
+ /* Find the second colon. */
+ const char *second_colon = strrchr(input, ':'), *first_colon;
+ char *endptr = 0;
+ if (!second_colon || second_colon == input) {
+ fprintf(stderr, "could not parse filename:line:column in '%s'\n", input);
return 1;
}
- if (!strcmp(argv[2], "all") || !strcmp(argv[2], "local")) {
- clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
- clang_disposeTranslationUnit(TU);
+ /* Parse the column number. */
+ *column = strtol(second_colon + 1, &endptr, 10);
+ if (*endptr != 0) {
+ fprintf(stderr, "could not parse column in '%s'\n", input);
return 1;
}
- /* Perform some simple filtering. */
- if (!strcmp(argv[2], "category")) K = CXCursor_ObjCCategoryDecl;
- else if (!strcmp(argv[2], "interface")) K = CXCursor_ObjCInterfaceDecl;
- else if (!strcmp(argv[2], "protocol")) K = CXCursor_ObjCProtocolDecl;
- else if (!strcmp(argv[2], "function")) K = CXCursor_FunctionDecl;
- else if (!strcmp(argv[2], "typedef")) K = CXCursor_TypedefDecl;
- clang_loadTranslationUnit(TU, TranslationUnitVisitor, &K);
- clang_disposeTranslationUnit(TU);
- return 1;
+ /* Find the first colon. */
+ first_colon = second_colon - 1;
+ while (first_colon != input && *first_colon != ':')
+ --first_colon;
+ if (first_colon == input) {
+ fprintf(stderr, "could not parse line in '%s'\n", input);
+ return 1;
+ }
+
+ /* Parse the line number. */
+ *line = strtol(first_colon + 1, &endptr, 10);
+ if (*endptr != ':') {
+ fprintf(stderr, "could not parse line in '%s'\n", input);
+ return 1;
+ }
+
+ /* Copy the file name. */
+ *filename = (char*)malloc(first_colon - input + 1);
+ memcpy(*filename, input, first_colon - input);
+ (*filename)[first_colon - input] = 0;
+ return 0;
+}
+
+const char *
+clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) {
+ switch (Kind) {
+ case CXCompletionChunk_Optional: return "Optional";
+ case CXCompletionChunk_TypedText: return "TypedText";
+ case CXCompletionChunk_Text: return "Text";
+ case CXCompletionChunk_Placeholder: return "Placeholder";
+ case CXCompletionChunk_Informative: return "Informative";
+ case CXCompletionChunk_CurrentParameter: return "CurrentParameter";
+ case CXCompletionChunk_LeftParen: return "LeftParen";
+ case CXCompletionChunk_RightParen: return "RightParen";
+ case CXCompletionChunk_LeftBracket: return "LeftBracket";
+ case CXCompletionChunk_RightBracket: return "RightBracket";
+ case CXCompletionChunk_LeftBrace: return "LeftBrace";
+ case CXCompletionChunk_RightBrace: return "RightBrace";
+ case CXCompletionChunk_LeftAngle: return "LeftAngle";
+ case CXCompletionChunk_RightAngle: return "RightAngle";
+ case CXCompletionChunk_Comma: return "Comma";
}
+
+ return "Unknown";
+}
+
+void print_completion_string(CXCompletionString completion_string, FILE *file) {
+ int I, N;
+
+ N = clang_getNumCompletionChunks(completion_string);
+ for (I = 0; I != N; ++I) {
+ const char *text = 0;
+ enum CXCompletionChunkKind Kind
+ = clang_getCompletionChunkKind(completion_string, I);
+
+ if (Kind == CXCompletionChunk_Optional) {
+ fprintf(file, "{Optional ");
+ print_completion_string(
+ clang_getCompletionChunkCompletionString(completion_string, I),
+ file);
+ fprintf(file, "}");
+ continue;
+ }
+
+ text = clang_getCompletionChunkText(completion_string, I);
+ fprintf(file, "{%s %s}",
+ clang_getCompletionChunkKindSpelling(Kind),
+ text? text : "");
+ }
+}
+
+void print_completion_result(CXCompletionResult *completion_result,
+ CXClientData client_data) {
+ FILE *file = (FILE *)client_data;
+ fprintf(file, "%s:",
+ clang_getCursorKindSpelling(completion_result->CursorKind));
+ print_completion_string(completion_result->CompletionString, file);
+ fprintf(file, "\n");
+}
+
+int perform_code_completion(int argc, const char **argv) {
+ const char *input = argv[1];
+ char *filename = 0;
+ unsigned line;
+ unsigned column;
+ CXIndex CIdx;
+ int errorCode;
+
+ input += strlen("-code-completion-at=");
+ if ((errorCode = parse_file_line_column(input, &filename, &line, &column)))
+ return errorCode;
+
+ CIdx = clang_createIndex(0, 0);
+ clang_codeComplete(CIdx, argv[argc - 1], argc - 3, argv + 2,
+ filename, line, column, &print_completion_result, stdout);
+ clang_disposeIndex(CIdx);
+ free(filename);
+
+ return 0;
+}
+
+/******************************************************************************/
+/* Command line processing. */
+/******************************************************************************/
+
+static void print_usage(void) {
+ fprintf(stderr,
+ "usage: c-index-test -code-completion-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>\n\n"
+ " <symbol filter> options for -test-load-tu:\n%s",
+ " all - load all symbols, including those from PCH\n"
+ " local - load all symbols except those in PCH\n"
+ " category - only load ObjC categories (non-PCH)\n"
+ " interface - only load ObjC interfaces (non-PCH)\n"
+ " protocol - only load ObjC protocols (non-PCH)\n"
+ " function - only load functions (non-PCH)\n"
+ " typedef - only load typdefs (non-PCH)\n\n");
+}
+
+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 == 4 && strcmp(argv[1], "-test-load-tu") == 0)
+ return perform_test_load_tu(argv[2], argv[3]);
+ if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
+ return perform_file_scan(argv[2], argv[3],
+ argc >= 5 ? argv[4] : 0);
+
+ print_usage();
+ return 1;
}
diff --git a/tools/clang-cc/CMakeLists.txt b/tools/clang-cc/CMakeLists.txt
index 85e4c7c20653..e7da908fdd06 100644
--- a/tools/clang-cc/CMakeLists.txt
+++ b/tools/clang-cc/CMakeLists.txt
@@ -23,6 +23,7 @@ set( LLVM_LINK_COMPONENTS
add_clang_executable(clang-cc
clang-cc.cpp
+ Options.cpp
)
add_dependencies(clang-cc clang-headers)
diff --git a/tools/clang-cc/Options.cpp b/tools/clang-cc/Options.cpp
new file mode 100644
index 000000000000..b5190ebcae54
--- /dev/null
+++ b/tools/clang-cc/Options.cpp
@@ -0,0 +1,1330 @@
+//===--- Options.cpp - clang-cc Option Handling ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This file contains "pure" option handling, it is only responsible for turning
+// the options into internal *Option classes, but shouldn't have any other
+// logic.
+
+#include "Options.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/AnalysisConsumer.h"
+#include "clang/CodeGen/CodeGenOptions.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/PreprocessorOptions.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/RegistryParser.h"
+#include "llvm/System/Host.h"
+#include <stdio.h>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Analyzer Options
+//===----------------------------------------------------------------------===//
+
+namespace analyzeroptions {
+
+static llvm::cl::list<Analyses>
+AnalysisList(llvm::cl::desc("Source Code Analysis - Checks and Analyses"),
+llvm::cl::values(
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
+clEnumValN(NAME, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<AnalysisStores>
+AnalysisStoreOpt("analyzer-store",
+ llvm::cl::desc("Source Code Analysis - Abstract Memory Store Models"),
+ llvm::cl::init(BasicStoreModel),
+ llvm::cl::values(
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)\
+clEnumValN(NAME##Model, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<AnalysisConstraints>
+AnalysisConstraintsOpt("analyzer-constraints",
+ llvm::cl::desc("Source Code Analysis - Symbolic Constraint Engines"),
+ llvm::cl::init(RangeConstraintsModel),
+ llvm::cl::values(
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)\
+clEnumValN(NAME##Model, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<AnalysisDiagClients>
+AnalysisDiagOpt("analyzer-output",
+ llvm::cl::desc("Source Code Analysis - Output Options"),
+ llvm::cl::init(PD_HTML),
+ llvm::cl::values(
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE)\
+clEnumValN(PD_##NAME, CMDFLAG, DESC),
+#include "clang/Frontend/Analyses.def"
+clEnumValEnd));
+
+static llvm::cl::opt<bool>
+AnalyzeAll("analyzer-opt-analyze-headers",
+ llvm::cl::desc("Force the static analyzer to analyze "
+ "functions defined in header files"));
+
+static llvm::cl::opt<bool>
+AnalyzerDisplayProgress("analyzer-display-progress",
+ llvm::cl::desc("Emit verbose output about the analyzer's progress"));
+
+static llvm::cl::opt<bool>
+AnalyzerExperimentalChecks("analyzer-experimental-checks",
+ llvm::cl::desc("Use experimental path-sensitive checks"));
+
+static llvm::cl::opt<bool>
+AnalyzerExperimentalInternalChecks("analyzer-experimental-internal-checks",
+ llvm::cl::desc("Use new default path-sensitive checks currently in testing"));
+
+static llvm::cl::opt<std::string>
+AnalyzeSpecificFunction("analyze-function",
+ llvm::cl::desc("Run analysis on specific function"));
+
+static llvm::cl::opt<bool>
+EagerlyAssume("analyzer-eagerly-assume",
+ llvm::cl::init(false),
+ llvm::cl::desc("Eagerly assume the truth/falseness of some "
+ "symbolic constraints"));
+
+static llvm::cl::opt<bool>
+PurgeDead("analyzer-purge-dead",
+ llvm::cl::init(true),
+ llvm::cl::desc("Remove dead symbols, bindings, and constraints before"
+ " processing a statement"));
+
+static llvm::cl::opt<bool>
+TrimGraph("trim-egraph",
+ llvm::cl::desc("Only show error-related paths in the analysis graph"));
+
+static llvm::cl::opt<bool>
+VisualizeEGDot("analyzer-viz-egraph-graphviz",
+ llvm::cl::desc("Display exploded graph using GraphViz"));
+
+static llvm::cl::opt<bool>
+VisualizeEGUbi("analyzer-viz-egraph-ubigraph",
+ llvm::cl::desc("Display exploded graph using Ubigraph"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation Options
+//===----------------------------------------------------------------------===//
+
+namespace codegenoptions {
+
+static llvm::cl::opt<bool>
+DisableLLVMOptimizations("disable-llvm-optzns",
+ llvm::cl::desc("Don't run LLVM optimization passes"));
+
+static llvm::cl::opt<bool>
+DisableRedZone("disable-red-zone",
+ llvm::cl::desc("Do not emit code that uses the red zone."),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+GenerateDebugInfo("g",
+ llvm::cl::desc("Generate source level debug information"));
+
+static llvm::cl::opt<bool>
+NoCommon("fno-common",
+ llvm::cl::desc("Compile common globals like normal definitions"),
+ llvm::cl::ValueDisallowed);
+
+static llvm::cl::opt<bool>
+NoImplicitFloat("no-implicit-float",
+ llvm::cl::desc("Don't generate implicit floating point instructions (x86-only)"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+NoMergeConstants("fno-merge-all-constants",
+ llvm::cl::desc("Disallow merging of constants."));
+
+// It might be nice to add bounds to the CommandLine library directly.
+struct OptLevelParser : public llvm::cl::parser<unsigned> {
+ bool parse(llvm::cl::Option &O, llvm::StringRef ArgName,
+ llvm::StringRef Arg, unsigned &Val) {
+ if (llvm::cl::parser<unsigned>::parse(O, ArgName, Arg, Val))
+ return true;
+ if (Val > 3)
+ return O.error("'" + Arg + "' invalid optimization level!");
+ return false;
+ }
+};
+static llvm::cl::opt<unsigned, false, OptLevelParser>
+OptLevel("O", llvm::cl::Prefix,
+ llvm::cl::desc("Optimization level"),
+ llvm::cl::init(0));
+
+static llvm::cl::opt<bool>
+OptSize("Os", llvm::cl::desc("Optimize for size"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Dependency Output Options
+//===----------------------------------------------------------------------===//
+
+namespace dependencyoutputoptions {
+
+static llvm::cl::opt<std::string>
+DependencyFile("dependency-file",
+ llvm::cl::desc("Filename (or -) to write dependency output to"));
+
+static llvm::cl::opt<bool>
+DependenciesIncludeSystemHeaders("sys-header-deps",
+ llvm::cl::desc("Include system headers in dependency output"));
+
+static llvm::cl::list<std::string>
+DependencyTargets("MT",
+ llvm::cl::desc("Specify target for dependency"));
+
+static llvm::cl::opt<bool>
+PhonyDependencyTarget("MP",
+ llvm::cl::desc("Create phony target for each dependency "
+ "(other than main file)"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Options
+//===----------------------------------------------------------------------===//
+
+namespace diagnosticoptions {
+
+static llvm::cl::opt<std::string>
+DumpBuildInformation("dump-build-information",
+ llvm::cl::value_desc("filename"),
+ llvm::cl::desc("output a dump of some build information to a file"));
+
+static llvm::cl::opt<bool>
+NoShowColumn("fno-show-column",
+ llvm::cl::desc("Do not include column number on diagnostics"));
+
+static llvm::cl::opt<bool>
+NoShowLocation("fno-show-source-location",
+ llvm::cl::desc("Do not include source location information with"
+ " diagnostics"));
+
+static llvm::cl::opt<bool>
+NoCaretDiagnostics("fno-caret-diagnostics",
+ llvm::cl::desc("Do not include source line and caret with"
+ " diagnostics"));
+
+static llvm::cl::opt<bool>
+NoDiagnosticsFixIt("fno-diagnostics-fixit-info",
+ llvm::cl::desc("Do not include fixit information in"
+ " diagnostics"));
+
+static llvm::cl::opt<bool> OptNoWarnings("w");
+
+static llvm::cl::opt<bool> OptPedantic("pedantic");
+
+static llvm::cl::opt<bool> OptPedanticErrors("pedantic-errors");
+
+// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
+// driver has stripped off -Wa,foo etc. The driver has also translated -W to
+// -Wextra, so we don't need to worry about it.
+static llvm::cl::list<std::string>
+OptWarnings("W", llvm::cl::Prefix, llvm::cl::ValueOptional);
+
+static llvm::cl::opt<bool>
+PrintSourceRangeInfo("fdiagnostics-print-source-range-info",
+ llvm::cl::desc("Print source range spans in numeric form"));
+
+static llvm::cl::opt<bool>
+PrintDiagnosticOption("fdiagnostics-show-option",
+ llvm::cl::desc("Print diagnostic name with mappable diagnostics"));
+
+static llvm::cl::opt<unsigned>
+MessageLength("fmessage-length",
+ llvm::cl::desc("Format message diagnostics so that they fit "
+ "within N columns or fewer, when possible."),
+ llvm::cl::value_desc("N"));
+
+static llvm::cl::opt<bool>
+PrintColorDiagnostic("fcolor-diagnostics",
+ llvm::cl::desc("Use colors in diagnostics"));
+
+static llvm::cl::opt<bool>
+SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::init(false),
+ llvm::cl::desc("Silence ObjC rewriting warnings"));
+
+static llvm::cl::opt<bool>
+VerifyDiagnostics("verify",
+ llvm::cl::desc("Verify emitted diagnostics and warnings"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Frontend Options
+//===----------------------------------------------------------------------===//
+
+namespace frontendoptions {
+
+using namespace clang::frontend;
+
+static llvm::cl::opt<ParsedSourceLocation>
+CodeCompletionAt("code-completion-at",
+ llvm::cl::value_desc("file:line:column"),
+ llvm::cl::desc("Dump code-completion information at a location"));
+
+static llvm::cl::opt<bool>
+CodeCompletionDebugPrinter("code-completion-debug-printer",
+ llvm::cl::desc("Use the \"debug\" code-completion print"),
+ llvm::cl::init(true));
+
+static llvm::cl::opt<bool>
+CodeCompletionWantsMacros("code-completion-macros",
+ llvm::cl::desc("Include macros in code-completion results"));
+
+static llvm::cl::opt<bool>
+DisableFree("disable-free",
+ llvm::cl::desc("Disable freeing of memory on exit"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+EmptyInputOnly("empty-input-only",
+ llvm::cl::desc("Force running on an empty input file"));
+
+static llvm::cl::opt<FrontendOptions::InputKind>
+InputType("x", llvm::cl::desc("Input language type"),
+ llvm::cl::init(FrontendOptions::IK_None),
+ llvm::cl::values(clEnumValN(FrontendOptions::IK_C, "c", "C"),
+ clEnumValN(FrontendOptions::IK_OpenCL, "cl", "OpenCL C"),
+ clEnumValN(FrontendOptions::IK_CXX, "c++", "C++"),
+ clEnumValN(FrontendOptions::IK_ObjC, "objective-c",
+ "Objective C"),
+ clEnumValN(FrontendOptions::IK_ObjCXX, "objective-c++",
+ "Objective C++"),
+ clEnumValN(FrontendOptions::IK_PreprocessedC,
+ "cpp-output",
+ "Preprocessed C"),
+ clEnumValN(FrontendOptions::IK_Asm,
+ "assembler-with-cpp",
+ "Assembly Source Codde"),
+ clEnumValN(FrontendOptions::IK_PreprocessedCXX,
+ "c++-cpp-output",
+ "Preprocessed C++"),
+ clEnumValN(FrontendOptions::IK_PreprocessedObjC,
+ "objective-c-cpp-output",
+ "Preprocessed Objective C"),
+ clEnumValN(FrontendOptions::IK_PreprocessedObjCXX,
+ "objective-c++-cpp-output",
+ "Preprocessed Objective C++"),
+ clEnumValN(FrontendOptions::IK_C, "c-header",
+ "C header"),
+ clEnumValN(FrontendOptions::IK_ObjC, "objective-c-header",
+ "Objective-C header"),
+ clEnumValN(FrontendOptions::IK_CXX, "c++-header",
+ "C++ header"),
+ clEnumValN(FrontendOptions::IK_ObjCXX,
+ "objective-c++-header",
+ "Objective-C++ header"),
+ clEnumValN(FrontendOptions::IK_AST, "ast",
+ "Clang AST"),
+ clEnumValEnd));
+
+static llvm::cl::list<std::string>
+InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
+
+static llvm::cl::opt<std::string>
+InheritanceViewCls("cxx-inheritance-view",
+ llvm::cl::value_desc("class name"),
+ llvm::cl::desc("View C++ inheritance for a specified class"));
+
+static llvm::cl::list<ParsedSourceLocation>
+FixItAtLocations("fixit-at", llvm::cl::value_desc("source-location"),
+ llvm::cl::desc("Perform Fix-It modifications at the given source location"));
+
+static llvm::cl::opt<std::string>
+OutputFile("o",
+ llvm::cl::value_desc("path"),
+ llvm::cl::desc("Specify output file"));
+
+static llvm::cl::opt<std::string>
+PluginActionName("plugin",
+ llvm::cl::desc("Use the named plugin action "
+ "(use \"help\" to list available options)"));
+
+static llvm::cl::opt<ActionKind>
+ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
+ llvm::cl::init(ParseSyntaxOnly),
+ llvm::cl::values(
+ clEnumValN(RunPreprocessorOnly, "Eonly",
+ "Just run preprocessor, no output (for timings)"),
+ clEnumValN(PrintPreprocessedInput, "E",
+ "Run preprocessor, emit preprocessed file"),
+ clEnumValN(DumpRawTokens, "dump-raw-tokens",
+ "Lex file in raw mode and dump raw tokens"),
+ clEnumValN(RunAnalysis, "analyze",
+ "Run static analysis engine"),
+ clEnumValN(DumpTokens, "dump-tokens",
+ "Run preprocessor, dump internal rep of tokens"),
+ clEnumValN(ParseNoop, "parse-noop",
+ "Run parser with noop callbacks (for timings)"),
+ clEnumValN(ParseSyntaxOnly, "fsyntax-only",
+ "Run parser and perform semantic analysis"),
+ clEnumValN(FixIt, "fixit",
+ "Apply fix-it advice to the input source"),
+ clEnumValN(ParsePrintCallbacks, "parse-print-callbacks",
+ "Run parser and print each callback invoked"),
+ clEnumValN(EmitHTML, "emit-html",
+ "Output input source as HTML"),
+ clEnumValN(ASTPrint, "ast-print",
+ "Build ASTs and then pretty-print them"),
+ clEnumValN(ASTPrintXML, "ast-print-xml",
+ "Build ASTs and then print them in XML format"),
+ clEnumValN(ASTDump, "ast-dump",
+ "Build ASTs and then debug dump them"),
+ clEnumValN(ASTView, "ast-view",
+ "Build ASTs and view them with GraphViz"),
+ clEnumValN(PrintDeclContext, "print-decl-contexts",
+ "Print DeclContexts and their Decls"),
+ clEnumValN(DumpRecordLayouts, "dump-record-layouts",
+ "Dump record layout information"),
+ clEnumValN(GeneratePTH, "emit-pth",
+ "Generate pre-tokenized header file"),
+ clEnumValN(GeneratePCH, "emit-pch",
+ "Generate pre-compiled header file"),
+ clEnumValN(EmitAssembly, "S",
+ "Emit native assembly code"),
+ clEnumValN(EmitLLVM, "emit-llvm",
+ "Build ASTs then convert to LLVM, emit .ll file"),
+ clEnumValN(EmitBC, "emit-llvm-bc",
+ "Build ASTs then convert to LLVM, emit .bc file"),
+ clEnumValN(EmitLLVMOnly, "emit-llvm-only",
+ "Build ASTs and convert to LLVM, discarding output"),
+ clEnumValN(RewriteTest, "rewrite-test",
+ "Rewriter playground"),
+ clEnumValN(RewriteObjC, "rewrite-objc",
+ "Rewrite ObjC into C (code rewriter example)"),
+ clEnumValN(RewriteMacros, "rewrite-macros",
+ "Expand macros without full preprocessing"),
+ clEnumValN(RewriteBlocks, "rewrite-blocks",
+ "Rewrite Blocks to C"),
+ clEnumValEnd));
+
+static llvm::cl::opt<bool>
+RelocatablePCH("relocatable-pch",
+ llvm::cl::desc("Whether to build a relocatable precompiled "
+ "header"));
+static llvm::cl::opt<bool>
+Stats("print-stats",
+ llvm::cl::desc("Print performance metrics and statistics"));
+
+static llvm::cl::opt<bool>
+TimeReport("ftime-report",
+ llvm::cl::desc("Print the amount of time each "
+ "phase of compilation takes"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Language Options
+//===----------------------------------------------------------------------===//
+
+namespace langoptions {
+
+static llvm::cl::opt<bool>
+AllowBuiltins("fbuiltin", llvm::cl::init(true),
+ llvm::cl::desc("Disable implicit builtin knowledge of functions"));
+
+static llvm::cl::opt<bool>
+AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+AccessControl("faccess-control",
+ llvm::cl::desc("Enable C++ access control"));
+
+static llvm::cl::opt<bool>
+CharIsSigned("fsigned-char",
+ llvm::cl::desc("Force char to be a signed/unsigned type"));
+
+static llvm::cl::opt<bool>
+DollarsInIdents("fdollars-in-identifiers",
+ llvm::cl::desc("Allow '$' in identifiers"));
+
+static llvm::cl::opt<bool>
+EmitAllDecls("femit-all-decls",
+ llvm::cl::desc("Emit all declarations, even if unused"));
+
+static llvm::cl::opt<bool>
+EnableBlocks("fblocks", llvm::cl::desc("enable the 'blocks' language feature"));
+
+static llvm::cl::opt<bool>
+EnableHeinousExtensions("fheinous-gnu-extensions",
+ llvm::cl::desc("enable GNU extensions that you really really shouldn't use"),
+ llvm::cl::ValueDisallowed, llvm::cl::Hidden);
+
+static llvm::cl::opt<bool>
+Exceptions("fexceptions",
+ llvm::cl::desc("Enable support for exception handling"));
+
+static llvm::cl::opt<bool>
+Freestanding("ffreestanding",
+ llvm::cl::desc("Assert that the compilation takes place in a "
+ "freestanding environment"));
+
+static llvm::cl::opt<bool>
+GNURuntime("fgnu-runtime",
+ llvm::cl::desc("Generate output compatible with the standard GNU "
+ "Objective-C runtime"));
+
+/// LangStds - Language standards we support.
+enum LangStds {
+ lang_unspecified,
+ lang_c89, lang_c94, lang_c99,
+ lang_gnu89, lang_gnu99,
+ lang_cxx98, lang_gnucxx98,
+ lang_cxx0x, lang_gnucxx0x
+};
+static llvm::cl::opt<LangStds>
+LangStd("std", llvm::cl::desc("Language standard to compile for"),
+ llvm::cl::init(lang_unspecified),
+ llvm::cl::values(clEnumValN(lang_c89, "c89", "ISO C 1990"),
+ clEnumValN(lang_c89, "c90", "ISO C 1990"),
+ clEnumValN(lang_c89, "iso9899:1990", "ISO C 1990"),
+ clEnumValN(lang_c94, "iso9899:199409",
+ "ISO C 1990 with amendment 1"),
+ clEnumValN(lang_c99, "c99", "ISO C 1999"),
+ clEnumValN(lang_c99, "c9x", "ISO C 1999"),
+ clEnumValN(lang_c99, "iso9899:1999", "ISO C 1999"),
+ clEnumValN(lang_c99, "iso9899:199x", "ISO C 1999"),
+ clEnumValN(lang_gnu89, "gnu89",
+ "ISO C 1990 with GNU extensions"),
+ clEnumValN(lang_gnu99, "gnu99",
+ "ISO C 1999 with GNU extensions (default for C)"),
+ clEnumValN(lang_gnu99, "gnu9x",
+ "ISO C 1999 with GNU extensions"),
+ clEnumValN(lang_cxx98, "c++98",
+ "ISO C++ 1998 with amendments"),
+ clEnumValN(lang_gnucxx98, "gnu++98",
+ "ISO C++ 1998 with amendments and GNU "
+ "extensions (default for C++)"),
+ clEnumValN(lang_cxx0x, "c++0x",
+ "Upcoming ISO C++ 200x with amendments"),
+ clEnumValN(lang_gnucxx0x, "gnu++0x",
+ "Upcoming ISO C++ 200x with amendments and GNU "
+ "extensions"),
+ clEnumValEnd));
+
+static llvm::cl::opt<bool>
+MSExtensions("fms-extensions",
+ llvm::cl::desc("Accept some non-standard constructs used in "
+ "Microsoft header files "));
+
+static llvm::cl::opt<std::string>
+MainFileName("main-file-name",
+ llvm::cl::desc("Main file name to use for debug info"));
+
+static llvm::cl::opt<bool>
+MathErrno("fmath-errno", llvm::cl::init(true),
+ llvm::cl::desc("Require math functions to respect errno"));
+
+static llvm::cl::opt<bool>
+NoElideConstructors("fno-elide-constructors",
+ llvm::cl::desc("Disable C++ copy constructor elision"));
+
+static llvm::cl::opt<bool>
+NoLaxVectorConversions("fno-lax-vector-conversions",
+ llvm::cl::desc("Disallow implicit conversions between "
+ "vectors with a different number of "
+ "elements or different element types"));
+
+
+static llvm::cl::opt<bool>
+NoOperatorNames("fno-operator-names",
+ llvm::cl::desc("Do not treat C++ operator name keywords as "
+ "synonyms for operators"));
+
+static llvm::cl::opt<std::string>
+ObjCConstantStringClass("fconstant-string-class",
+ llvm::cl::value_desc("class name"),
+ llvm::cl::desc("Specify the class to use for constant "
+ "Objective-C string objects."));
+
+static llvm::cl::opt<bool>
+ObjCEnableGC("fobjc-gc",
+ llvm::cl::desc("Enable Objective-C garbage collection"));
+
+static llvm::cl::opt<bool>
+ObjCExclusiveGC("fobjc-gc-only",
+ llvm::cl::desc("Use GC exclusively for Objective-C related "
+ "memory management"));
+
+static llvm::cl::opt<bool>
+ObjCEnableGCBitmapPrint("print-ivar-layout",
+ llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace"));
+
+static llvm::cl::opt<bool>
+ObjCNonFragileABI("fobjc-nonfragile-abi",
+ llvm::cl::desc("enable objective-c's nonfragile abi"));
+
+static llvm::cl::opt<bool>
+OverflowChecking("ftrapv",
+ llvm::cl::desc("Trap on integer overflow"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<unsigned>
+PICLevel("pic-level", llvm::cl::desc("Value for __PIC__"));
+
+static llvm::cl::opt<bool>
+PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code"),
+ llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+PascalStrings("fpascal-strings",
+ llvm::cl::desc("Recognize and construct Pascal-style "
+ "string literals"));
+
+static llvm::cl::opt<bool>
+Rtti("frtti", llvm::cl::init(true),
+ llvm::cl::desc("Enable generation of rtti information"));
+
+static llvm::cl::opt<bool>
+ShortWChar("fshort-wchar",
+ llvm::cl::desc("Force wchar_t to be a short unsigned int"));
+
+static llvm::cl::opt<bool>
+StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
+
+static llvm::cl::opt<int>
+StackProtector("stack-protector",
+ llvm::cl::desc("Enable stack protectors"),
+ llvm::cl::init(-1));
+
+static llvm::cl::opt<LangOptions::VisibilityMode>
+SymbolVisibility("fvisibility",
+ llvm::cl::desc("Set the default symbol visibility:"),
+ llvm::cl::init(LangOptions::Default),
+ llvm::cl::values(clEnumValN(LangOptions::Default, "default",
+ "Use default symbol visibility"),
+ clEnumValN(LangOptions::Hidden, "hidden",
+ "Use hidden symbol visibility"),
+ clEnumValN(LangOptions::Protected,"protected",
+ "Use protected symbol visibility"),
+ clEnumValEnd));
+
+static llvm::cl::opt<unsigned>
+TemplateDepth("ftemplate-depth", llvm::cl::init(99),
+ llvm::cl::desc("Maximum depth of recursive template "
+ "instantiation"));
+
+static llvm::cl::opt<bool>
+Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
+
+static llvm::cl::opt<bool>
+WritableStrings("fwritable-strings",
+ llvm::cl::desc("Store string literals as writable data"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// General Preprocessor Options
+//===----------------------------------------------------------------------===//
+
+namespace preprocessoroptions {
+
+static llvm::cl::list<std::string>
+D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
+ llvm::cl::desc("Predefine the specified macro"));
+
+static llvm::cl::list<std::string>
+ImplicitIncludes("include", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include file before parsing"));
+static llvm::cl::list<std::string>
+ImplicitMacroIncludes("imacros", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include macros from file before parsing"));
+
+static llvm::cl::opt<std::string>
+ImplicitIncludePCH("include-pch", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include precompiled header file"));
+
+static llvm::cl::opt<std::string>
+ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
+ llvm::cl::desc("Include file before parsing"));
+
+static llvm::cl::opt<std::string>
+TokenCache("token-cache", llvm::cl::value_desc("path"),
+ llvm::cl::desc("Use specified token cache file"));
+
+static llvm::cl::list<std::string>
+U_macros("U", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
+ llvm::cl::desc("Undefine the specified macro"));
+
+static llvm::cl::opt<bool>
+UndefMacros("undef", llvm::cl::value_desc("macro"),
+ llvm::cl::desc("undef all system defines"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Header Search Options
+//===----------------------------------------------------------------------===//
+
+namespace headersearchoptions {
+
+static llvm::cl::opt<bool>
+nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories"));
+
+static llvm::cl::opt<bool>
+nobuiltininc("nobuiltininc",
+ llvm::cl::desc("Disable builtin #include directories"));
+
+// Various command line options. These four add directories to each chain.
+static llvm::cl::list<std::string>
+F_dirs("F", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to framework include search path"));
+
+static llvm::cl::list<std::string>
+I_dirs("I", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to include search path"));
+
+static llvm::cl::list<std::string>
+idirafter_dirs("idirafter", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to AFTER include search path"));
+
+static llvm::cl::list<std::string>
+iquote_dirs("iquote", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to QUOTE include search path"));
+
+static llvm::cl::list<std::string>
+isystem_dirs("isystem", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+ llvm::cl::desc("Add directory to SYSTEM include search path"));
+
+// These handle -iprefix/-iwithprefix/-iwithprefixbefore.
+static llvm::cl::list<std::string>
+iprefix_vals("iprefix", llvm::cl::value_desc("prefix"), llvm::cl::Prefix,
+ llvm::cl::desc("Set the -iwithprefix/-iwithprefixbefore prefix"));
+static llvm::cl::list<std::string>
+iwithprefix_vals("iwithprefix", llvm::cl::value_desc("dir"), llvm::cl::Prefix,
+ llvm::cl::desc("Set directory to SYSTEM include search path with prefix"));
+static llvm::cl::list<std::string>
+iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"),
+ llvm::cl::Prefix,
+ llvm::cl::desc("Set directory to include search path with prefix"));
+
+static llvm::cl::opt<std::string>
+isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"),
+ llvm::cl::desc("Set the system root directory (usually /)"));
+
+static llvm::cl::opt<bool>
+Verbose("v", llvm::cl::desc("Enable verbose output"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessed Output Options
+//===----------------------------------------------------------------------===//
+
+namespace preprocessoroutputoptions {
+
+static llvm::cl::opt<bool>
+DisableLineMarkers("P", llvm::cl::desc("Disable linemarker output in -E mode"));
+
+static llvm::cl::opt<bool>
+EnableCommentOutput("C", llvm::cl::desc("Enable comment output in -E mode"));
+
+static llvm::cl::opt<bool>
+EnableMacroCommentOutput("CC",
+ llvm::cl::desc("Enable comment output in -E mode, "
+ "even from macro expansions"));
+static llvm::cl::opt<bool>
+DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of"
+ " normal output"));
+static llvm::cl::opt<bool>
+DumpDefines("dD", llvm::cl::desc("Print macro definitions in -E mode in "
+ "addition to normal output"));
+
+}
+//===----------------------------------------------------------------------===//
+// Target Options
+//===----------------------------------------------------------------------===//
+
+namespace targetoptions {
+
+static llvm::cl::opt<std::string>
+TargetABI("target-abi",
+ llvm::cl::desc("Target a particular ABI type"));
+
+static llvm::cl::opt<std::string>
+TargetCPU("mcpu",
+ llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"));
+
+static llvm::cl::list<std::string>
+TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes"));
+
+static llvm::cl::opt<std::string>
+TargetTriple("triple",
+ llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
+
+}
+
+//===----------------------------------------------------------------------===//
+// Option Object Construction
+//===----------------------------------------------------------------------===//
+
+void clang::InitializeAnalyzerOptions(AnalyzerOptions &Opts) {
+ using namespace analyzeroptions;
+ Opts.AnalysisList = AnalysisList;
+ Opts.AnalysisStoreOpt = AnalysisStoreOpt;
+ Opts.AnalysisConstraintsOpt = AnalysisConstraintsOpt;
+ Opts.AnalysisDiagOpt = AnalysisDiagOpt;
+ Opts.VisualizeEGDot = VisualizeEGDot;
+ Opts.VisualizeEGUbi = VisualizeEGUbi;
+ Opts.AnalyzeAll = AnalyzeAll;
+ Opts.AnalyzerDisplayProgress = AnalyzerDisplayProgress;
+ Opts.PurgeDead = PurgeDead;
+ Opts.EagerlyAssume = EagerlyAssume;
+ Opts.AnalyzeSpecificFunction = AnalyzeSpecificFunction;
+ Opts.EnableExperimentalChecks = AnalyzerExperimentalChecks;
+ Opts.EnableExperimentalInternalChecks = AnalyzerExperimentalInternalChecks;
+ Opts.TrimGraph = TrimGraph;
+}
+
+void clang::InitializeCodeGenOptions(CodeGenOptions &Opts,
+ const LangOptions &Lang,
+ bool TimePasses) {
+ using namespace codegenoptions;
+
+ // -Os implies -O2
+ Opts.OptimizationLevel = OptSize ? 2 : OptLevel;
+
+ // We must always run at least the always inlining pass.
+ Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
+ : CodeGenOptions::OnlyAlwaysInlining;
+
+ Opts.DebugInfo = GenerateDebugInfo;
+ Opts.DisableLLVMOpts = DisableLLVMOptimizations;
+ Opts.DisableRedZone = DisableRedZone;
+ Opts.MergeAllConstants = !NoMergeConstants;
+ Opts.NoCommon = NoCommon;
+ Opts.NoImplicitFloat = NoImplicitFloat;
+ Opts.OptimizeSize = OptSize;
+ Opts.SimplifyLibCalls = 1;
+ Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !OptSize);
+
+ // FIXME: Eliminate this dependency?
+ if (Lang.NoBuiltin)
+ Opts.SimplifyLibCalls = 0;
+ if (Lang.CPlusPlus)
+ Opts.NoCommon = 1;
+ Opts.TimePasses = TimePasses;
+
+#ifdef NDEBUG
+ Opts.VerifyModule = 0;
+#endif
+}
+
+void clang::InitializeDependencyOutputOptions(DependencyOutputOptions &Opts) {
+ using namespace dependencyoutputoptions;
+
+ Opts.OutputFile = DependencyFile;
+ Opts.Targets = DependencyTargets;
+ Opts.IncludeSystemHeaders = DependenciesIncludeSystemHeaders;
+ Opts.UsePhonyTargets = PhonyDependencyTarget;
+}
+
+void clang::InitializeDiagnosticOptions(DiagnosticOptions &Opts) {
+ using namespace diagnosticoptions;
+
+ Opts.Warnings = OptWarnings;
+ Opts.DumpBuildInformation = DumpBuildInformation;
+ Opts.IgnoreWarnings = OptNoWarnings;
+ Opts.MessageLength = MessageLength;
+ Opts.NoRewriteMacros = SilenceRewriteMacroWarning;
+ Opts.Pedantic = OptPedantic;
+ Opts.PedanticErrors = OptPedanticErrors;
+ Opts.ShowCarets = !NoCaretDiagnostics;
+ Opts.ShowColors = PrintColorDiagnostic;
+ Opts.ShowColumn = !NoShowColumn;
+ Opts.ShowFixits = !NoDiagnosticsFixIt;
+ Opts.ShowLocation = !NoShowLocation;
+ Opts.ShowOptionNames = PrintDiagnosticOption;
+ Opts.ShowSourceRanges = PrintSourceRangeInfo;
+ Opts.VerifyDiagnostics = VerifyDiagnostics;
+}
+
+void clang::InitializeFrontendOptions(FrontendOptions &Opts) {
+ using namespace frontendoptions;
+
+ // Select program action.
+ Opts.ProgramAction = ProgAction;
+ if (PluginActionName.getPosition()) {
+ Opts.ProgramAction = frontend::PluginAction;
+ Opts.ActionName = PluginActionName;
+ }
+
+ Opts.CodeCompletionAt = CodeCompletionAt;
+ Opts.DebugCodeCompletionPrinter = CodeCompletionDebugPrinter;
+ Opts.DisableFree = DisableFree;
+ Opts.EmptyInputOnly = EmptyInputOnly;
+ Opts.FixItLocations = FixItAtLocations;
+ Opts.OutputFile = OutputFile;
+ Opts.RelocatablePCH = RelocatablePCH;
+ Opts.ShowMacrosInCodeCompletion = CodeCompletionWantsMacros;
+ Opts.ShowStats = Stats;
+ Opts.ShowTimers = TimeReport;
+ Opts.ViewClassInheritance = InheritanceViewCls;
+
+ // '-' is the default input if none is given.
+ if (InputFilenames.empty()) {
+ FrontendOptions::InputKind IK = InputType;
+ if (IK == FrontendOptions::IK_None) IK = FrontendOptions::IK_C;
+ Opts.Inputs.push_back(std::make_pair(IK, "-"));
+ } else {
+ for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
+ FrontendOptions::InputKind IK = InputType;
+ llvm::StringRef Ext =
+ llvm::StringRef(InputFilenames[i]).rsplit('.').second;
+ if (IK == FrontendOptions::IK_None)
+ IK = FrontendOptions::getInputKindForExtension(Ext);
+ Opts.Inputs.push_back(std::make_pair(IK, InputFilenames[i]));
+ }
+ }
+}
+
+void clang::InitializeHeaderSearchOptions(HeaderSearchOptions &Opts,
+ llvm::StringRef BuiltinIncludePath) {
+ using namespace headersearchoptions;
+
+ Opts.Sysroot = isysroot;
+ Opts.Verbose = Verbose;
+
+ // Handle -I... and -F... options, walking the lists in parallel.
+ unsigned Iidx = 0, Fidx = 0;
+ while (Iidx < I_dirs.size() && Fidx < F_dirs.size()) {
+ if (I_dirs.getPosition(Iidx) < F_dirs.getPosition(Fidx)) {
+ Opts.AddPath(I_dirs[Iidx], frontend::Angled, true, false);
+ ++Iidx;
+ } else {
+ Opts.AddPath(F_dirs[Fidx], frontend::Angled, true, true);
+ ++Fidx;
+ }
+ }
+
+ // Consume what's left from whatever list was longer.
+ for (; Iidx != I_dirs.size(); ++Iidx)
+ Opts.AddPath(I_dirs[Iidx], frontend::Angled, true, false);
+ for (; Fidx != F_dirs.size(); ++Fidx)
+ Opts.AddPath(F_dirs[Fidx], frontend::Angled, true, true);
+
+ // Handle -idirafter... options.
+ for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i)
+ Opts.AddPath(idirafter_dirs[i], frontend::After, true, false);
+
+ // Handle -iquote... options.
+ for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i)
+ Opts.AddPath(iquote_dirs[i], frontend::Quoted, true, false);
+
+ // Handle -isystem... options.
+ for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i)
+ Opts.AddPath(isystem_dirs[i], frontend::System, true, false);
+
+ // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in
+ // parallel, processing the values in order of occurance to get the right
+ // prefixes.
+ {
+ std::string Prefix = ""; // FIXME: this isn't the correct default prefix.
+ unsigned iprefix_idx = 0;
+ unsigned iwithprefix_idx = 0;
+ unsigned iwithprefixbefore_idx = 0;
+ bool iprefix_done = iprefix_vals.empty();
+ bool iwithprefix_done = iwithprefix_vals.empty();
+ bool iwithprefixbefore_done = iwithprefixbefore_vals.empty();
+ while (!iprefix_done || !iwithprefix_done || !iwithprefixbefore_done) {
+ if (!iprefix_done &&
+ (iwithprefix_done ||
+ iprefix_vals.getPosition(iprefix_idx) <
+ iwithprefix_vals.getPosition(iwithprefix_idx)) &&
+ (iwithprefixbefore_done ||
+ iprefix_vals.getPosition(iprefix_idx) <
+ iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
+ Prefix = iprefix_vals[iprefix_idx];
+ ++iprefix_idx;
+ iprefix_done = iprefix_idx == iprefix_vals.size();
+ } else if (!iwithprefix_done &&
+ (iwithprefixbefore_done ||
+ iwithprefix_vals.getPosition(iwithprefix_idx) <
+ iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
+ Opts.AddPath(Prefix+iwithprefix_vals[iwithprefix_idx],
+ frontend::System, false, false);
+ ++iwithprefix_idx;
+ iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size();
+ } else {
+ Opts.AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx],
+ frontend::Angled, false, false);
+ ++iwithprefixbefore_idx;
+ iwithprefixbefore_done =
+ iwithprefixbefore_idx == iwithprefixbefore_vals.size();
+ }
+ }
+ }
+
+ // Add CPATH environment paths.
+ if (const char *Env = getenv("CPATH"))
+ Opts.EnvIncPath = Env;
+
+ // Add language specific environment paths.
+ if (const char *Env = getenv("OBJCPLUS_INCLUDE_PATH"))
+ Opts.ObjCXXEnvIncPath = Env;
+ if (const char *Env = getenv("CPLUS_INCLUDE_PATH"))
+ Opts.CXXEnvIncPath = Env;
+ if (const char *Env = getenv("OBJC_INCLUDE_PATH"))
+ Opts.CEnvIncPath = Env;
+ if (const char *Env = getenv("C_INCLUDE_PATH"))
+ Opts.CEnvIncPath = Env;
+
+ if (!nobuiltininc)
+ Opts.BuiltinIncludePath = BuiltinIncludePath;
+
+ Opts.UseStandardIncludes = !nostdinc;
+}
+
+void clang::InitializePreprocessorOptions(PreprocessorOptions &Opts) {
+ using namespace preprocessoroptions;
+
+ Opts.ImplicitPCHInclude = ImplicitIncludePCH;
+ Opts.ImplicitPTHInclude = ImplicitIncludePTH;
+
+ // Select the token cache file, we don't support more than one currently so we
+ // can't have both an implicit-pth and a token cache file.
+ if (TokenCache.getPosition() && ImplicitIncludePTH.getPosition()) {
+ // FIXME: Don't fail like this.
+ fprintf(stderr, "error: cannot use both -token-cache and -include-pth "
+ "options\n");
+ exit(1);
+ }
+ if (TokenCache.getPosition())
+ Opts.TokenCache = TokenCache;
+ else
+ Opts.TokenCache = ImplicitIncludePTH;
+
+ // Use predefines?
+ Opts.UsePredefines = !UndefMacros;
+
+ // Add macros from the command line.
+ unsigned d = 0, D = D_macros.size();
+ unsigned u = 0, U = U_macros.size();
+ while (d < D || u < U) {
+ if (u == U || (d < D && D_macros.getPosition(d) < U_macros.getPosition(u)))
+ Opts.addMacroDef(D_macros[d++]);
+ else
+ Opts.addMacroUndef(U_macros[u++]);
+ }
+
+ // If -imacros are specified, include them now. These are processed before
+ // any -include directives.
+ for (unsigned i = 0, e = ImplicitMacroIncludes.size(); i != e; ++i)
+ Opts.MacroIncludes.push_back(ImplicitMacroIncludes[i]);
+
+ // Add the ordered list of -includes, sorting in the implicit include options
+ // at the appropriate location.
+ llvm::SmallVector<std::pair<unsigned, std::string*>, 8> OrderedPaths;
+ std::string OriginalFile;
+
+ if (!ImplicitIncludePTH.empty())
+ OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(),
+ &ImplicitIncludePTH));
+ if (!ImplicitIncludePCH.empty()) {
+ OriginalFile = PCHReader::getOriginalSourceFile(ImplicitIncludePCH);
+ // FIXME: Don't fail like this.
+ if (OriginalFile.empty())
+ exit(1);
+ OrderedPaths.push_back(std::make_pair(ImplicitIncludePCH.getPosition(),
+ &OriginalFile));
+ }
+ for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i)
+ OrderedPaths.push_back(std::make_pair(ImplicitIncludes.getPosition(i),
+ &ImplicitIncludes[i]));
+ llvm::array_pod_sort(OrderedPaths.begin(), OrderedPaths.end());
+
+ for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i)
+ Opts.Includes.push_back(*OrderedPaths[i].second);
+}
+
+void clang::InitializeLangOptions(LangOptions &Options,
+ FrontendOptions::InputKind IK,
+ TargetInfo &Target) {
+ using namespace langoptions;
+
+
+ switch (IK) {
+ case FrontendOptions::IK_None:
+ case FrontendOptions::IK_AST:
+ assert(0 && "Invalid input kind!");
+ case FrontendOptions::IK_Asm:
+ Options.AsmPreprocessor = 1;
+ // FALLTHROUGH
+ case FrontendOptions::IK_PreprocessedC:
+ // FALLTHROUGH
+ case FrontendOptions::IK_C:
+ // Do nothing.
+ break;
+ case FrontendOptions::IK_PreprocessedCXX:
+ // FALLTHROUGH
+ case FrontendOptions::IK_CXX:
+ Options.CPlusPlus = 1;
+ break;
+ case FrontendOptions::IK_PreprocessedObjC:
+ // FALLTHROUGH
+ case FrontendOptions::IK_ObjC:
+ Options.ObjC1 = Options.ObjC2 = 1;
+ break;
+ case FrontendOptions::IK_PreprocessedObjCXX:
+ // FALLTHROUGH
+ case FrontendOptions::IK_ObjCXX:
+ Options.ObjC1 = Options.ObjC2 = 1;
+ Options.CPlusPlus = 1;
+ break;
+ case FrontendOptions::IK_OpenCL:
+ Options.OpenCL = 1;
+ Options.AltiVec = 1;
+ Options.CXXOperatorNames = 1;
+ Options.LaxVectorConversions = 1;
+ break;
+ }
+
+ if (ObjCExclusiveGC)
+ Options.setGCMode(LangOptions::GCOnly);
+ else if (ObjCEnableGC)
+ Options.setGCMode(LangOptions::HybridGC);
+
+ if (ObjCEnableGCBitmapPrint)
+ Options.ObjCGCBitmapPrint = 1;
+
+ if (AltiVec)
+ Options.AltiVec = 1;
+
+ if (PThread)
+ Options.POSIXThreads = 1;
+
+ Options.setVisibilityMode(SymbolVisibility);
+ Options.OverflowChecking = OverflowChecking;
+
+ if (LangStd == lang_unspecified) {
+ // Based on the base language, pick one.
+ switch (IK) {
+ case FrontendOptions::IK_None:
+ case FrontendOptions::IK_AST:
+ assert(0 && "Invalid input kind!");
+ case FrontendOptions::IK_OpenCL:
+ LangStd = lang_c99;
+ break;
+ case FrontendOptions::IK_Asm:
+ case FrontendOptions::IK_C:
+ case FrontendOptions::IK_PreprocessedC:
+ case FrontendOptions::IK_ObjC:
+ case FrontendOptions::IK_PreprocessedObjC:
+ LangStd = lang_gnu99;
+ break;
+ case FrontendOptions::IK_CXX:
+ case FrontendOptions::IK_PreprocessedCXX:
+ case FrontendOptions::IK_ObjCXX:
+ case FrontendOptions::IK_PreprocessedObjCXX:
+ LangStd = lang_gnucxx98;
+ break;
+ }
+ }
+
+ switch (LangStd) {
+ default: assert(0 && "Unknown language standard!");
+
+ // Fall through from newer standards to older ones. This isn't really right.
+ // FIXME: Enable specifically the right features based on the language stds.
+ case lang_gnucxx0x:
+ case lang_cxx0x:
+ Options.CPlusPlus0x = 1;
+ // FALL THROUGH
+ case lang_gnucxx98:
+ case lang_cxx98:
+ Options.CPlusPlus = 1;
+ Options.CXXOperatorNames = !NoOperatorNames;
+ // FALL THROUGH.
+ case lang_gnu99:
+ case lang_c99:
+ Options.C99 = 1;
+ Options.HexFloats = 1;
+ // FALL THROUGH.
+ case lang_gnu89:
+ Options.BCPLComment = 1; // Only for C99/C++.
+ // FALL THROUGH.
+ case lang_c94:
+ Options.Digraphs = 1; // C94, C99, C++.
+ // FALL THROUGH.
+ case lang_c89:
+ break;
+ }
+
+ // GNUMode - Set if we're in gnu99, gnu89, gnucxx98, etc.
+ switch (LangStd) {
+ default: assert(0 && "Unknown language standard!");
+ case lang_gnucxx0x:
+ case lang_gnucxx98:
+ case lang_gnu99:
+ case lang_gnu89:
+ Options.GNUMode = 1;
+ break;
+ case lang_cxx0x:
+ case lang_cxx98:
+ case lang_c99:
+ case lang_c94:
+ case lang_c89:
+ Options.GNUMode = 0;
+ break;
+ }
+
+ if (Options.CPlusPlus) {
+ Options.C99 = 0;
+ Options.HexFloats = 0;
+ }
+
+ if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89)
+ Options.ImplicitInt = 1;
+ else
+ Options.ImplicitInt = 0;
+
+ // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+ // is specified, or -std is set to a conforming mode.
+ Options.Trigraphs = !Options.GNUMode;
+ if (Trigraphs.getPosition())
+ Options.Trigraphs = Trigraphs; // Command line option wins if specified.
+
+ // If in a conformant language mode (e.g. -std=c99) Blocks defaults to off
+ // even if they are normally on for the target. In GNU modes (e.g.
+ // -std=gnu99) the default for blocks depends on the target settings.
+ // However, blocks are not turned off when compiling Obj-C or Obj-C++ code.
+ if (!Options.ObjC1 && !Options.GNUMode)
+ Options.Blocks = 0;
+
+ // Default to not accepting '$' in identifiers when preprocessing assembler,
+ // but do accept when preprocessing C. FIXME: these defaults are right for
+ // darwin, are they right everywhere?
+ Options.DollarIdents = IK != FrontendOptions::IK_Asm;
+ if (DollarsInIdents.getPosition()) // Explicit setting overrides default.
+ Options.DollarIdents = DollarsInIdents;
+
+ if (PascalStrings.getPosition())
+ Options.PascalStrings = PascalStrings;
+ if (MSExtensions.getPosition())
+ Options.Microsoft = MSExtensions;
+ Options.WritableStrings = WritableStrings;
+ if (NoLaxVectorConversions.getPosition())
+ Options.LaxVectorConversions = 0;
+ Options.Exceptions = Exceptions;
+ Options.Rtti = Rtti;
+ if (EnableBlocks.getPosition())
+ Options.Blocks = EnableBlocks;
+ if (CharIsSigned.getPosition())
+ Options.CharIsSigned = CharIsSigned;
+ if (ShortWChar.getPosition())
+ Options.ShortWChar = ShortWChar;
+
+ if (!AllowBuiltins)
+ Options.NoBuiltin = 1;
+ if (Freestanding)
+ Options.Freestanding = Options.NoBuiltin = 1;
+
+ if (EnableHeinousExtensions)
+ Options.HeinousExtensions = 1;
+
+ if (AccessControl)
+ Options.AccessControl = 1;
+
+ Options.ElideConstructors = !NoElideConstructors;
+
+ // OpenCL and C++ both have bool, true, false keywords.
+ Options.Bool = Options.OpenCL | Options.CPlusPlus;
+
+ Options.MathErrno = MathErrno;
+
+ Options.InstantiationDepth = TemplateDepth;
+
+ // Override the default runtime if the user requested it.
+ if (GNURuntime)
+ Options.NeXTRuntime = 0;
+
+ if (!ObjCConstantStringClass.empty())
+ Options.ObjCConstantStringClass = ObjCConstantStringClass.c_str();
+
+ if (ObjCNonFragileABI)
+ Options.ObjCNonFragileABI = 1;
+
+ if (EmitAllDecls)
+ Options.EmitAllDecls = 1;
+
+ // The __OPTIMIZE_SIZE__ define is tied to -Oz, which we don't support.
+ Options.OptimizeSize = 0;
+ Options.Optimize = codegenoptions::OptSize || codegenoptions::OptLevel;
+
+ assert(PICLevel <= 2 && "Invalid value for -pic-level");
+ Options.PICLevel = PICLevel;
+
+ Options.GNUInline = !Options.C99;
+
+ // This is the __NO_INLINE__ define, which just depends on things like the
+ // optimization level and -fno-inline, not actually whether the backend has
+ // inlining enabled.
+ //
+ // FIXME: This is affected by other options (-fno-inline).
+ Options.NoInline = !codegenoptions::OptLevel;
+
+ Options.Static = StaticDefine;
+
+ switch (StackProtector) {
+ default:
+ assert(StackProtector <= 2 && "Invalid value for -stack-protector");
+ case -1: break;
+ case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break;
+ case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break;
+ case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break;
+ }
+
+ if (MainFileName.getPosition())
+ Options.setMainFileName(MainFileName.c_str());
+
+ Target.setForcedLangOptions(Options);
+}
+
+void
+clang::InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts) {
+ using namespace preprocessoroutputoptions;
+
+ Opts.ShowCPP = !DumpMacros;
+ Opts.ShowMacros = DumpMacros || DumpDefines;
+ Opts.ShowLineMarkers = !DisableLineMarkers;
+ Opts.ShowComments = EnableCommentOutput;
+ Opts.ShowMacroComments = EnableMacroCommentOutput;
+}
+
+void clang::InitializeTargetOptions(TargetOptions &Opts) {
+ using namespace targetoptions;
+
+ Opts.ABI = TargetABI;
+ Opts.CPU = TargetCPU;
+ Opts.Triple = TargetTriple;
+ Opts.Features = TargetFeatures;
+
+ // Use the host triple if unspecified.
+ if (Opts.Triple.empty())
+ Opts.Triple = llvm::sys::getHostTriple();
+}
diff --git a/tools/clang-cc/Options.h b/tools/clang-cc/Options.h
new file mode 100644
index 000000000000..9a2fd9d59a16
--- /dev/null
+++ b/tools/clang-cc/Options.h
@@ -0,0 +1,57 @@
+//===-- Options.h - clang-cc Option Handling --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANGCC_OPTIONS_H
+#define LLVM_CLANGCC_OPTIONS_H
+
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+class AnalyzerOptions;
+class CodeGenOptions;
+class DependencyOutputOptions;
+class DiagnosticOptions;
+class FrontendOptions;
+class HeaderSearchOptions;
+class LangOptions;
+class PreprocessorOptions;
+class PreprocessorOutputOptions;
+class TargetInfo;
+class TargetOptions;
+
+void InitializeAnalyzerOptions(AnalyzerOptions &Opts);
+
+void InitializeCodeGenOptions(CodeGenOptions &Opts,
+ const LangOptions &Lang,
+ bool TimePasses);
+
+void InitializeDependencyOutputOptions(DependencyOutputOptions &Opts);
+
+void InitializeDiagnosticOptions(DiagnosticOptions &Opts);
+
+void InitializeFrontendOptions(FrontendOptions &Opts);
+
+void InitializeHeaderSearchOptions(HeaderSearchOptions &Opts,
+ llvm::StringRef BuiltinIncludePath);
+
+void InitializeLangOptions(LangOptions &Options,
+ FrontendOptions::InputKind LK,
+ TargetInfo &Target);
+
+void InitializePreprocessorOptions(PreprocessorOptions &Opts);
+
+void InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts);
+
+void InitializeTargetOptions(TargetOptions &Opts);
+
+} // end namespace clang
+
+#endif
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index 26ba42d67002..bae8697e14bd 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -8,2122 +8,198 @@
//===----------------------------------------------------------------------===//
//
// This utility may be invoked in the following manner:
-// clang --help - Output help info.
-// clang [options] - Read from stdin.
-// clang [options] file - Read from "file".
-// clang [options] file1 file2 - Read these files.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: Options to support:
-//
-// -Wfatal-errors
-// -ftabstop=width
+// clang-cc --help - Output help info.
+// clang-cc [options] - Read from stdin.
+// clang-cc [options] file - Read from "file".
+// clang-cc [options] file1 file2 - Read these files.
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/AnalysisConsumer.h"
-#include "clang/Frontend/ASTConsumers.h"
-#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/CompileOptions.h"
-#include "clang/Frontend/DiagnosticOptions.h"
-#include "clang/Frontend/FixItRewriter.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/InitHeaderSearch.h"
-#include "clang/Frontend/InitPreprocessor.h"
-#include "clang/Frontend/PathDiagnosticClients.h"
-#include "clang/Frontend/PCHReader.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/CommandLineSourceLoc.h"
-#include "clang/Frontend/Utils.h"
-#include "clang/Analysis/PathDiagnostic.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Sema/CodeCompleteConsumer.h"
-#include "clang/Sema/ParseAST.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/LexDiagnostic.h"
+#include "Options.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
-#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetSelect.h"
-#include <cstdlib>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
using namespace clang;
//===----------------------------------------------------------------------===//
-// Source Location Parser
-//===----------------------------------------------------------------------===//
-
-static bool ResolveParsedLocation(ParsedSourceLocation &ParsedLoc,
- FileManager &FileMgr,
- RequestedSourceLocation &Result) {
- const FileEntry *File = FileMgr.getFile(ParsedLoc.FileName);
- if (!File)
- return true;
-
- Result.File = File;
- Result.Line = ParsedLoc.Line;
- Result.Column = ParsedLoc.Column;
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Global options.
-//===----------------------------------------------------------------------===//
-
-/// ClangFrontendTimer - The front-end activities should charge time to it with
-/// TimeRegion. The -ftime-report option controls whether this will do
-/// anything.
-llvm::Timer *ClangFrontendTimer = 0;
-
-static llvm::cl::opt<bool>
-Verbose("v", llvm::cl::desc("Enable verbose output"));
-static llvm::cl::opt<bool>
-Stats("print-stats",
- llvm::cl::desc("Print performance metrics and statistics"));
-static llvm::cl::opt<bool>
-DisableFree("disable-free",
- llvm::cl::desc("Disable freeing of memory on exit"),
- llvm::cl::init(false));
-static llvm::cl::opt<bool>
-EmptyInputOnly("empty-input-only",
- llvm::cl::desc("Force running on an empty input file"));
-
-enum ProgActions {
- RewriteObjC, // ObjC->C Rewriter.
- RewriteBlocks, // ObjC->C Rewriter for Blocks.
- RewriteMacros, // Expand macros but not #includes.
- RewriteTest, // Rewriter playground
- FixIt, // Fix-It Rewriter
- HTMLTest, // HTML displayer testing stuff.
- EmitAssembly, // Emit a .s file.
- EmitLLVM, // Emit a .ll file.
- EmitBC, // Emit a .bc file.
- EmitLLVMOnly, // Generate LLVM IR, but do not
- EmitHTML, // Translate input source into HTML.
- ASTPrint, // Parse ASTs and print them.
- ASTPrintXML, // Parse ASTs and print them in XML.
- ASTDump, // Parse ASTs and dump them.
- ASTView, // Parse ASTs and view them in Graphviz.
- PrintDeclContext, // Print DeclContext and their Decls.
- DumpRecordLayouts, // Dump record layout information.
- ParsePrintCallbacks, // Parse and print each callback.
- ParseSyntaxOnly, // Parse and perform semantic analysis.
- ParseNoop, // Parse with noop callbacks.
- RunPreprocessorOnly, // Just lex, no output.
- PrintPreprocessedInput, // -E mode.
- DumpTokens, // Dump out preprocessed tokens.
- DumpRawTokens, // Dump out raw tokens.
- RunAnalysis, // Run one or more source code analyses.
- GeneratePTH, // Generate pre-tokenized header.
- GeneratePCH, // Generate pre-compiled header.
- InheritanceView // View C++ inheritance for a specified class.
-};
-
-static llvm::cl::opt<ProgActions>
-ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
- llvm::cl::init(ParseSyntaxOnly),
- llvm::cl::values(
- clEnumValN(RunPreprocessorOnly, "Eonly",
- "Just run preprocessor, no output (for timings)"),
- clEnumValN(PrintPreprocessedInput, "E",
- "Run preprocessor, emit preprocessed file"),
- clEnumValN(DumpRawTokens, "dump-raw-tokens",
- "Lex file in raw mode and dump raw tokens"),
- clEnumValN(RunAnalysis, "analyze",
- "Run static analysis engine"),
- clEnumValN(DumpTokens, "dump-tokens",
- "Run preprocessor, dump internal rep of tokens"),
- clEnumValN(ParseNoop, "parse-noop",
- "Run parser with noop callbacks (for timings)"),
- clEnumValN(ParseSyntaxOnly, "fsyntax-only",
- "Run parser and perform semantic analysis"),
- clEnumValN(ParsePrintCallbacks, "parse-print-callbacks",
- "Run parser and print each callback invoked"),
- clEnumValN(EmitHTML, "emit-html",
- "Output input source as HTML"),
- clEnumValN(ASTPrint, "ast-print",
- "Build ASTs and then pretty-print them"),
- clEnumValN(ASTPrintXML, "ast-print-xml",
- "Build ASTs and then print them in XML format"),
- clEnumValN(ASTDump, "ast-dump",
- "Build ASTs and then debug dump them"),
- clEnumValN(ASTView, "ast-view",
- "Build ASTs and view them with GraphViz"),
- clEnumValN(PrintDeclContext, "print-decl-contexts",
- "Print DeclContexts and their Decls"),
- clEnumValN(DumpRecordLayouts, "dump-record-layouts",
- "Dump record layout information"),
- clEnumValN(GeneratePTH, "emit-pth",
- "Generate pre-tokenized header file"),
- clEnumValN(GeneratePCH, "emit-pch",
- "Generate pre-compiled header file"),
- clEnumValN(EmitAssembly, "S",
- "Emit native assembly code"),
- clEnumValN(EmitLLVM, "emit-llvm",
- "Build ASTs then convert to LLVM, emit .ll file"),
- clEnumValN(EmitBC, "emit-llvm-bc",
- "Build ASTs then convert to LLVM, emit .bc file"),
- clEnumValN(EmitLLVMOnly, "emit-llvm-only",
- "Build ASTs and convert to LLVM, discarding output"),
- clEnumValN(RewriteTest, "rewrite-test",
- "Rewriter playground"),
- clEnumValN(RewriteObjC, "rewrite-objc",
- "Rewrite ObjC into C (code rewriter example)"),
- clEnumValN(RewriteMacros, "rewrite-macros",
- "Expand macros without full preprocessing"),
- clEnumValN(RewriteBlocks, "rewrite-blocks",
- "Rewrite Blocks to C"),
- clEnumValN(FixIt, "fixit",
- "Apply fix-it advice to the input source"),
- clEnumValEnd));
-
-
-static llvm::cl::opt<std::string>
-OutputFile("o",
- llvm::cl::value_desc("path"),
- llvm::cl::desc("Specify output file"));
-
-
-static llvm::cl::opt<ParsedSourceLocation>
-CodeCompletionAt("code-completion-at",
- llvm::cl::value_desc("file:line:column"),
- llvm::cl::desc("Dump code-completion information at a location"));
-
-/// \brief Buld a new code-completion consumer that prints the results of
-/// code completion to standard output.
-static CodeCompleteConsumer *BuildPrintingCodeCompleter(Sema &S, void *) {
- return new PrintingCodeCompleteConsumer(S, llvm::outs());
-}
-
-//===----------------------------------------------------------------------===//
-// PTH.
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<std::string>
-TokenCache("token-cache", llvm::cl::value_desc("path"),
- llvm::cl::desc("Use specified token cache file"));
-
-//===----------------------------------------------------------------------===//
-// Diagnostic Options
-//===----------------------------------------------------------------------===//
-
-static DiagnosticOptions DiagOpts;
-
-static llvm::cl::opt<bool>
-VerifyDiagnostics("verify",
- llvm::cl::desc("Verify emitted diagnostics and warnings"));
-
-static llvm::cl::opt<bool>
-NoShowColumn("fno-show-column",
- llvm::cl::desc("Do not include column number on diagnostics"));
-
-static llvm::cl::opt<bool>
-NoShowLocation("fno-show-source-location",
- llvm::cl::desc("Do not include source location information with"
- " diagnostics"));
-
-static llvm::cl::opt<bool>
-NoCaretDiagnostics("fno-caret-diagnostics",
- llvm::cl::desc("Do not include source line and caret with"
- " diagnostics"));
-
-static llvm::cl::opt<bool>
-NoDiagnosticsFixIt("fno-diagnostics-fixit-info",
- llvm::cl::desc("Do not include fixit information in"
- " diagnostics"));
-
-static llvm::cl::opt<bool>
-PrintSourceRangeInfo("fdiagnostics-print-source-range-info",
- llvm::cl::desc("Print source range spans in numeric form"));
-
-static llvm::cl::opt<bool>
-PrintDiagnosticOption("fdiagnostics-show-option",
- llvm::cl::desc("Print diagnostic name with mappable diagnostics"));
-
-static llvm::cl::opt<unsigned>
-MessageLength("fmessage-length",
- llvm::cl::desc("Format message diagnostics so that they fit "
- "within N columns or fewer, when possible."),
- llvm::cl::value_desc("N"));
-
-static llvm::cl::opt<bool>
-PrintColorDiagnostic("fcolor-diagnostics",
- llvm::cl::desc("Use colors in diagnostics"));
-
-//===----------------------------------------------------------------------===//
-// C++ Visualization.
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<std::string>
-InheritanceViewCls("cxx-inheritance-view",
- llvm::cl::value_desc("class name"),
- llvm::cl::desc("View C++ inheritance for a specified class"));
-
-//===----------------------------------------------------------------------===//
-// Builtin Options
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<bool>
-TimeReport("ftime-report",
- llvm::cl::desc("Print the amount of time each "
- "phase of compilation takes"));
-
-static llvm::cl::opt<bool>
-Freestanding("ffreestanding",
- llvm::cl::desc("Assert that the compilation takes place in a "
- "freestanding environment"));
-
-static llvm::cl::opt<bool>
-AllowBuiltins("fbuiltin", llvm::cl::init(true),
- llvm::cl::desc("Disable implicit builtin knowledge of functions"));
-
-
-static llvm::cl::opt<bool>
-MathErrno("fmath-errno", llvm::cl::init(true),
- llvm::cl::desc("Require math functions to respect errno"));
-
-//===----------------------------------------------------------------------===//
-// Language Options
-//===----------------------------------------------------------------------===//
-
-enum LangKind {
- langkind_unspecified,
- langkind_c,
- langkind_c_cpp,
- langkind_asm_cpp,
- langkind_cxx,
- langkind_cxx_cpp,
- langkind_objc,
- langkind_objc_cpp,
- langkind_objcxx,
- langkind_objcxx_cpp,
- langkind_ocl,
- langkind_ast
-};
-
-static llvm::cl::opt<LangKind>
-BaseLang("x", llvm::cl::desc("Base language to compile"),
- llvm::cl::init(langkind_unspecified),
- llvm::cl::values(clEnumValN(langkind_c, "c", "C"),
- clEnumValN(langkind_ocl, "cl", "OpenCL C"),
- clEnumValN(langkind_cxx, "c++", "C++"),
- clEnumValN(langkind_objc, "objective-c", "Objective C"),
- clEnumValN(langkind_objcxx,"objective-c++","Objective C++"),
- clEnumValN(langkind_c_cpp, "cpp-output",
- "Preprocessed C"),
- clEnumValN(langkind_asm_cpp, "assembler-with-cpp",
- "Preprocessed asm"),
- clEnumValN(langkind_cxx_cpp, "c++-cpp-output",
- "Preprocessed C++"),
- clEnumValN(langkind_objc_cpp, "objective-c-cpp-output",
- "Preprocessed Objective C"),
- clEnumValN(langkind_objcxx_cpp, "objective-c++-cpp-output",
- "Preprocessed Objective C++"),
- clEnumValN(langkind_c, "c-header",
- "C header"),
- clEnumValN(langkind_objc, "objective-c-header",
- "Objective-C header"),
- clEnumValN(langkind_cxx, "c++-header",
- "C++ header"),
- clEnumValN(langkind_objcxx, "objective-c++-header",
- "Objective-C++ header"),
- clEnumValN(langkind_ast, "ast",
- "Clang AST"),
- clEnumValEnd));
-
-static llvm::cl::opt<bool>
-ObjCExclusiveGC("fobjc-gc-only",
- llvm::cl::desc("Use GC exclusively for Objective-C related "
- "memory management"));
-
-static llvm::cl::opt<std::string>
-ObjCConstantStringClass("fconstant-string-class",
- llvm::cl::value_desc("class name"),
- llvm::cl::desc("Specify the class to use for constant "
- "Objective-C string objects."));
-
-static llvm::cl::opt<bool>
-ObjCEnableGC("fobjc-gc",
- llvm::cl::desc("Enable Objective-C garbage collection"));
-
-static llvm::cl::opt<bool>
-ObjCEnableGCBitmapPrint("print-ivar-layout",
- llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace"));
-
-static llvm::cl::opt<LangOptions::VisibilityMode>
-SymbolVisibility("fvisibility",
- llvm::cl::desc("Set the default symbol visibility:"),
- llvm::cl::init(LangOptions::Default),
- llvm::cl::values(clEnumValN(LangOptions::Default, "default",
- "Use default symbol visibility"),
- clEnumValN(LangOptions::Hidden, "hidden",
- "Use hidden symbol visibility"),
- clEnumValN(LangOptions::Protected,"protected",
- "Use protected symbol visibility"),
- clEnumValEnd));
-
-static llvm::cl::opt<bool>
-OverflowChecking("ftrapv",
- llvm::cl::desc("Trap on integer overflow"),
- llvm::cl::init(false));
-
-static llvm::cl::opt<bool>
-AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax"),
- llvm::cl::init(false));
-
-static llvm::cl::opt<bool>
-PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code"),
- llvm::cl::init(false));
-
-static LangKind GetLanguage(llvm::StringRef Filename) {
- if (BaseLang != langkind_unspecified)
- return BaseLang;
-
- llvm::StringRef Ext = Filename.rsplit('.').second;
- if (Ext == "ast")
- return langkind_ast;
- else if (Ext == "c")
- return langkind_c;
- else if (Ext == "S" || Ext == "s")
- return langkind_asm_cpp;
- else if (Ext == "i")
- return langkind_c_cpp;
- else if (Ext == "ii")
- return langkind_cxx_cpp;
- else if (Ext == "m")
- return langkind_objc;
- else if (Ext == "mi")
- return langkind_objc_cpp;
- else if (Ext == "mm" || Ext == "M")
- return langkind_objcxx;
- else if (Ext == "mii")
- return langkind_objcxx_cpp;
- else if (Ext == "C" || Ext == "cc" || Ext == "cpp" || Ext == "CPP" ||
- Ext == "c++" || Ext == "cp" || Ext == "cxx")
- return langkind_cxx;
- else if (Ext == "cl")
- return langkind_ocl;
- else
- return langkind_c;
-}
-
-
-static void InitializeCOptions(LangOptions &Options) {
- // Do nothing.
-}
-
-static void InitializeObjCOptions(LangOptions &Options) {
- Options.ObjC1 = Options.ObjC2 = 1;
-}
-
-
-static void InitializeLangOptions(LangOptions &Options, LangKind LK){
- // FIXME: implement -fpreprocessed mode.
- bool NoPreprocess = false;
-
- switch (LK) {
- default: assert(0 && "Unknown language kind!");
- case langkind_asm_cpp:
- Options.AsmPreprocessor = 1;
- // FALLTHROUGH
- case langkind_c_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_c:
- InitializeCOptions(Options);
- break;
- case langkind_cxx_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_cxx:
- Options.CPlusPlus = 1;
- break;
- case langkind_objc_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_objc:
- InitializeObjCOptions(Options);
- break;
- case langkind_objcxx_cpp:
- NoPreprocess = true;
- // FALLTHROUGH
- case langkind_objcxx:
- Options.ObjC1 = Options.ObjC2 = 1;
- Options.CPlusPlus = 1;
- break;
- case langkind_ocl:
- Options.OpenCL = 1;
- Options.AltiVec = 1;
- Options.CXXOperatorNames = 1;
- Options.LaxVectorConversions = 1;
- break;
- }
-
- if (ObjCExclusiveGC)
- Options.setGCMode(LangOptions::GCOnly);
- else if (ObjCEnableGC)
- Options.setGCMode(LangOptions::HybridGC);
-
- if (ObjCEnableGCBitmapPrint)
- Options.ObjCGCBitmapPrint = 1;
-
- if (AltiVec)
- Options.AltiVec = 1;
-
- if (PThread)
- Options.POSIXThreads = 1;
-
- Options.setVisibilityMode(SymbolVisibility);
- Options.OverflowChecking = OverflowChecking;
-}
-
-/// LangStds - Language standards we support.
-enum LangStds {
- lang_unspecified,
- lang_c89, lang_c94, lang_c99,
- lang_gnu89, lang_gnu99,
- lang_cxx98, lang_gnucxx98,
- lang_cxx0x, lang_gnucxx0x
-};
-
-static llvm::cl::opt<LangStds>
-LangStd("std", llvm::cl::desc("Language standard to compile for"),
- llvm::cl::init(lang_unspecified),
- llvm::cl::values(clEnumValN(lang_c89, "c89", "ISO C 1990"),
- clEnumValN(lang_c89, "c90", "ISO C 1990"),
- clEnumValN(lang_c89, "iso9899:1990", "ISO C 1990"),
- clEnumValN(lang_c94, "iso9899:199409",
- "ISO C 1990 with amendment 1"),
- clEnumValN(lang_c99, "c99", "ISO C 1999"),
- clEnumValN(lang_c99, "c9x", "ISO C 1999"),
- clEnumValN(lang_c99, "iso9899:1999", "ISO C 1999"),
- clEnumValN(lang_c99, "iso9899:199x", "ISO C 1999"),
- clEnumValN(lang_gnu89, "gnu89",
- "ISO C 1990 with GNU extensions"),
- clEnumValN(lang_gnu99, "gnu99",
- "ISO C 1999 with GNU extensions (default for C)"),
- clEnumValN(lang_gnu99, "gnu9x",
- "ISO C 1999 with GNU extensions"),
- clEnumValN(lang_cxx98, "c++98",
- "ISO C++ 1998 with amendments"),
- clEnumValN(lang_gnucxx98, "gnu++98",
- "ISO C++ 1998 with amendments and GNU "
- "extensions (default for C++)"),
- clEnumValN(lang_cxx0x, "c++0x",
- "Upcoming ISO C++ 200x with amendments"),
- clEnumValN(lang_gnucxx0x, "gnu++0x",
- "Upcoming ISO C++ 200x with amendments and GNU "
- "extensions"),
- clEnumValEnd));
-
-static llvm::cl::opt<bool>
-NoOperatorNames("fno-operator-names",
- llvm::cl::desc("Do not treat C++ operator name keywords as "
- "synonyms for operators"));
-
-static llvm::cl::opt<bool>
-PascalStrings("fpascal-strings",
- llvm::cl::desc("Recognize and construct Pascal-style "
- "string literals"));
-
-static llvm::cl::opt<bool>
-MSExtensions("fms-extensions",
- llvm::cl::desc("Accept some non-standard constructs used in "
- "Microsoft header files "));
-
-static llvm::cl::opt<bool>
-WritableStrings("fwritable-strings",
- llvm::cl::desc("Store string literals as writable data"));
-
-static llvm::cl::opt<bool>
-NoLaxVectorConversions("fno-lax-vector-conversions",
- llvm::cl::desc("Disallow implicit conversions between "
- "vectors with a different number of "
- "elements or different element types"));
-
-static llvm::cl::opt<bool>
-EnableBlocks("fblocks", llvm::cl::desc("enable the 'blocks' language feature"));
-
-static llvm::cl::opt<bool>
-EnableHeinousExtensions("fheinous-gnu-extensions",
- llvm::cl::desc("enable GNU extensions that you really really shouldn't use"),
- llvm::cl::ValueDisallowed, llvm::cl::Hidden);
-
-static llvm::cl::opt<bool>
-ObjCNonFragileABI("fobjc-nonfragile-abi",
- llvm::cl::desc("enable objective-c's nonfragile abi"));
-
-
-static llvm::cl::opt<bool>
-EmitAllDecls("femit-all-decls",
- llvm::cl::desc("Emit all declarations, even if unused"));
-
-static llvm::cl::opt<bool>
-Exceptions("fexceptions",
- llvm::cl::desc("Enable support for exception handling"));
-
-static llvm::cl::opt<bool>
-Rtti("frtti", llvm::cl::init(true),
- llvm::cl::desc("Enable generation of rtti information"));
-
-static llvm::cl::opt<bool>
-GNURuntime("fgnu-runtime",
- llvm::cl::desc("Generate output compatible with the standard GNU "
- "Objective-C runtime"));
-
-static llvm::cl::opt<bool>
-NeXTRuntime("fnext-runtime",
- llvm::cl::desc("Generate output compatible with the NeXT "
- "runtime"));
-
-static llvm::cl::opt<bool>
-CharIsSigned("fsigned-char",
- llvm::cl::desc("Force char to be a signed/unsigned type"));
-
-
-static llvm::cl::opt<bool>
-Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
-
-static llvm::cl::opt<unsigned>
-TemplateDepth("ftemplate-depth", llvm::cl::init(99),
- llvm::cl::desc("Maximum depth of recursive template "
- "instantiation"));
-static llvm::cl::opt<bool>
-DollarsInIdents("fdollars-in-identifiers",
- llvm::cl::desc("Allow '$' in identifiers"));
-
-
-static llvm::cl::opt<bool>
-OptSize("Os", llvm::cl::desc("Optimize for size"));
-
-static llvm::cl::opt<bool>
-DisableLLVMOptimizations("disable-llvm-optzns",
- llvm::cl::desc("Don't run LLVM optimization passes"));
-
-static llvm::cl::opt<bool>
-NoCommon("fno-common",
- llvm::cl::desc("Compile common globals like normal definitions"),
- llvm::cl::ValueDisallowed);
-
-static llvm::cl::opt<std::string>
-MainFileName("main-file-name",
- llvm::cl::desc("Main file name to use for debug info"));
-
-// FIXME: Also add an "-fno-access-control" option.
-static llvm::cl::opt<bool>
-AccessControl("faccess-control",
- llvm::cl::desc("Enable C++ access control"));
-
-static llvm::cl::opt<bool>
-NoElideConstructors("fno-elide-constructors",
- llvm::cl::desc("Disable C++ copy constructor elision"));
-
-static llvm::cl::opt<bool>
-NoMergeConstants("fno-merge-all-constants",
- llvm::cl::desc("Disallow merging of constants."));
-
-static llvm::cl::opt<std::string>
-TargetABI("target-abi",
- llvm::cl::desc("Target a particular ABI type"));
-
-static llvm::cl::opt<std::string>
-TargetTriple("triple",
- llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
-
-
-// It might be nice to add bounds to the CommandLine library directly.
-struct OptLevelParser : public llvm::cl::parser<unsigned> {
- bool parse(llvm::cl::Option &O, llvm::StringRef ArgName,
- llvm::StringRef Arg, unsigned &Val) {
- if (llvm::cl::parser<unsigned>::parse(O, ArgName, Arg, Val))
- return true;
- if (Val > 3)
- return O.error("'" + Arg + "' invalid optimization level!");
- return false;
- }
-};
-static llvm::cl::opt<unsigned, false, OptLevelParser>
-OptLevel("O", llvm::cl::Prefix,
- llvm::cl::desc("Optimization level"),
- llvm::cl::init(0));
-
-static llvm::cl::opt<unsigned>
-PICLevel("pic-level", llvm::cl::desc("Value for __PIC__"));
-
-static llvm::cl::opt<bool>
-StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
-
-static llvm::cl::opt<int>
-StackProtector("stack-protector",
- llvm::cl::desc("Enable stack protectors"),
- llvm::cl::init(-1));
-
-static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
- TargetInfo *Target,
- const llvm::StringMap<bool> &Features) {
- // Allow the target to set the default the langauge options as it sees fit.
- Target->getDefaultLangOptions(Options);
-
- // Pass the map of target features to the target for validation and
- // processing.
- Target->HandleTargetFeatures(Features);
-
- if (LangStd == lang_unspecified) {
- // Based on the base language, pick one.
- switch (LK) {
- case langkind_ast: assert(0 && "Invalid call for AST inputs");
- case lang_unspecified: assert(0 && "Unknown base language");
- case langkind_ocl:
- LangStd = lang_c99;
- break;
- case langkind_c:
- case langkind_asm_cpp:
- case langkind_c_cpp:
- case langkind_objc:
- case langkind_objc_cpp:
- LangStd = lang_gnu99;
- break;
- case langkind_cxx:
- case langkind_cxx_cpp:
- case langkind_objcxx:
- case langkind_objcxx_cpp:
- LangStd = lang_gnucxx98;
- break;
- }
- }
-
- switch (LangStd) {
- default: assert(0 && "Unknown language standard!");
-
- // Fall through from newer standards to older ones. This isn't really right.
- // FIXME: Enable specifically the right features based on the language stds.
- case lang_gnucxx0x:
- case lang_cxx0x:
- Options.CPlusPlus0x = 1;
- // FALL THROUGH
- case lang_gnucxx98:
- case lang_cxx98:
- Options.CPlusPlus = 1;
- Options.CXXOperatorNames = !NoOperatorNames;
- // FALL THROUGH.
- case lang_gnu99:
- case lang_c99:
- Options.C99 = 1;
- Options.HexFloats = 1;
- // FALL THROUGH.
- case lang_gnu89:
- Options.BCPLComment = 1; // Only for C99/C++.
- // FALL THROUGH.
- case lang_c94:
- Options.Digraphs = 1; // C94, C99, C++.
- // FALL THROUGH.
- case lang_c89:
- break;
- }
-
- // GNUMode - Set if we're in gnu99, gnu89, gnucxx98, etc.
- switch (LangStd) {
- default: assert(0 && "Unknown language standard!");
- case lang_gnucxx0x:
- case lang_gnucxx98:
- case lang_gnu99:
- case lang_gnu89:
- Options.GNUMode = 1;
- break;
- case lang_cxx0x:
- case lang_cxx98:
- case lang_c99:
- case lang_c94:
- case lang_c89:
- Options.GNUMode = 0;
- break;
- }
-
- if (Options.CPlusPlus) {
- Options.C99 = 0;
- Options.HexFloats = 0;
- }
-
- if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89)
- Options.ImplicitInt = 1;
- else
- Options.ImplicitInt = 0;
-
- // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
- // is specified, or -std is set to a conforming mode.
- Options.Trigraphs = !Options.GNUMode;
- if (Trigraphs.getPosition())
- Options.Trigraphs = Trigraphs; // Command line option wins if specified.
-
- // If in a conformant language mode (e.g. -std=c99) Blocks defaults to off
- // even if they are normally on for the target. In GNU modes (e.g.
- // -std=gnu99) the default for blocks depends on the target settings.
- // However, blocks are not turned off when compiling Obj-C or Obj-C++ code.
- if (!Options.ObjC1 && !Options.GNUMode)
- Options.Blocks = 0;
-
- // Default to not accepting '$' in identifiers when preprocessing assembler,
- // but do accept when preprocessing C. FIXME: these defaults are right for
- // darwin, are they right everywhere?
- Options.DollarIdents = LK != langkind_asm_cpp;
- if (DollarsInIdents.getPosition()) // Explicit setting overrides default.
- Options.DollarIdents = DollarsInIdents;
-
- if (PascalStrings.getPosition())
- Options.PascalStrings = PascalStrings;
- if (MSExtensions.getPosition())
- Options.Microsoft = MSExtensions;
- Options.WritableStrings = WritableStrings;
- if (NoLaxVectorConversions.getPosition())
- Options.LaxVectorConversions = 0;
- Options.Exceptions = Exceptions;
- Options.Rtti = Rtti;
- if (EnableBlocks.getPosition())
- Options.Blocks = EnableBlocks;
- if (CharIsSigned.getPosition())
- Options.CharIsSigned = CharIsSigned;
-
- if (!AllowBuiltins)
- Options.NoBuiltin = 1;
- if (Freestanding)
- Options.Freestanding = Options.NoBuiltin = 1;
-
- if (EnableHeinousExtensions)
- Options.HeinousExtensions = 1;
-
- if (AccessControl)
- Options.AccessControl = 1;
-
- Options.ElideConstructors = !NoElideConstructors;
-
- // OpenCL and C++ both have bool, true, false keywords.
- Options.Bool = Options.OpenCL | Options.CPlusPlus;
-
- Options.MathErrno = MathErrno;
-
- Options.InstantiationDepth = TemplateDepth;
-
- // Override the default runtime if the user requested it.
- if (NeXTRuntime)
- Options.NeXTRuntime = 1;
- else if (GNURuntime)
- Options.NeXTRuntime = 0;
-
- if (!ObjCConstantStringClass.empty())
- Options.ObjCConstantStringClass = ObjCConstantStringClass.c_str();
-
- if (ObjCNonFragileABI)
- Options.ObjCNonFragileABI = 1;
-
- if (EmitAllDecls)
- Options.EmitAllDecls = 1;
-
- // The __OPTIMIZE_SIZE__ define is tied to -Oz, which we don't
- // support.
- Options.OptimizeSize = 0;
-
- // -Os implies -O2
- if (OptSize || OptLevel)
- Options.Optimize = 1;
-
- assert(PICLevel <= 2 && "Invalid value for -pic-level");
- Options.PICLevel = PICLevel;
-
- Options.GNUInline = !Options.C99;
- // FIXME: This is affected by other options (-fno-inline).
- Options.NoInline = !OptSize && !OptLevel;
-
- Options.Static = StaticDefine;
-
- switch (StackProtector) {
- default:
- assert(StackProtector <= 2 && "Invalid value for -stack-protector");
- case -1: break;
- case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break;
- case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break;
- case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break;
- }
-
- if (MainFileName.getPosition())
- Options.setMainFileName(MainFileName.c_str());
-}
-
-//===----------------------------------------------------------------------===//
-// SourceManager initialization.
-//===----------------------------------------------------------------------===//
-
-static bool InitializeSourceManager(Preprocessor &PP,
- const std::string &InFile) {
- // Figure out where to get and map in the main file.
- SourceManager &SourceMgr = PP.getSourceManager();
- FileManager &FileMgr = PP.getFileManager();
-
- if (EmptyInputOnly) {
- const char *EmptyStr = "";
- llvm::MemoryBuffer *SB =
- llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
- SourceMgr.createMainFileIDForMemBuffer(SB);
- } else if (InFile != "-") {
- const FileEntry *File = FileMgr.getFile(InFile);
- if (File) SourceMgr.createMainFileID(File, SourceLocation());
- if (SourceMgr.getMainFileID().isInvalid()) {
- PP.getDiagnostics().Report(FullSourceLoc(), diag::err_fe_error_reading)
- << InFile.c_str();
- return true;
- }
- } else {
- llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
-
- // If stdin was empty, SB is null. Cons up an empty memory
- // buffer now.
- if (!SB) {
- const char *EmptyStr = "";
- SB = llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<stdin>");
- }
-
- SourceMgr.createMainFileIDForMemBuffer(SB);
- if (SourceMgr.getMainFileID().isInvalid()) {
- PP.getDiagnostics().Report(FullSourceLoc(),
- diag::err_fe_error_reading_stdin);
- return true;
- }
- }
-
- return false;
-}
-
-
-//===----------------------------------------------------------------------===//
-// Preprocessor Initialization
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<bool>
-UndefMacros("undef", llvm::cl::value_desc("macro"),
- llvm::cl::desc("undef all system defines"));
-
-static llvm::cl::list<std::string>
-D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
- llvm::cl::desc("Predefine the specified macro"));
-static llvm::cl::list<std::string>
-U_macros("U", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
- llvm::cl::desc("Undefine the specified macro"));
-
-static llvm::cl::list<std::string>
-ImplicitIncludes("include", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include file before parsing"));
-static llvm::cl::list<std::string>
-ImplicitMacroIncludes("imacros", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include macros from file before parsing"));
-
-static llvm::cl::opt<std::string>
-ImplicitIncludePCH("include-pch", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include precompiled header file"));
-
-static llvm::cl::opt<std::string>
-ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
- llvm::cl::desc("Include file before parsing"));
-
-static llvm::cl::opt<bool>
-RelocatablePCH("relocatable-pch",
- llvm::cl::desc("Whether to build a relocatable precompiled "
- "header"));
-
-//===----------------------------------------------------------------------===//
-// Preprocessor include path information.
-//===----------------------------------------------------------------------===//
-
-// This tool exports a large number of command line options to control how the
-// preprocessor searches for header files. At root, however, the Preprocessor
-// object takes a very simple interface: a list of directories to search for
-//
-// FIXME: -nostdinc++
-// FIXME: -imultilib
-//
-
-static llvm::cl::opt<bool>
-nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories"));
-
-static llvm::cl::opt<bool>
-nobuiltininc("nobuiltininc",
- llvm::cl::desc("Disable builtin #include directories"));
-
-// Various command line options. These four add directories to each chain.
-static llvm::cl::list<std::string>
-F_dirs("F", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to framework include search path"));
-static llvm::cl::list<std::string>
-I_dirs("I", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to include search path"));
-static llvm::cl::list<std::string>
-idirafter_dirs("idirafter", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to AFTER include search path"));
-static llvm::cl::list<std::string>
-iquote_dirs("iquote", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to QUOTE include search path"));
-static llvm::cl::list<std::string>
-isystem_dirs("isystem", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
- llvm::cl::desc("Add directory to SYSTEM include search path"));
-
-// These handle -iprefix/-iwithprefix/-iwithprefixbefore.
-static llvm::cl::list<std::string>
-iprefix_vals("iprefix", llvm::cl::value_desc("prefix"), llvm::cl::Prefix,
- llvm::cl::desc("Set the -iwithprefix/-iwithprefixbefore prefix"));
-static llvm::cl::list<std::string>
-iwithprefix_vals("iwithprefix", llvm::cl::value_desc("dir"), llvm::cl::Prefix,
- llvm::cl::desc("Set directory to SYSTEM include search path with prefix"));
-static llvm::cl::list<std::string>
-iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"),
- llvm::cl::Prefix,
- llvm::cl::desc("Set directory to include search path with prefix"));
-
-static llvm::cl::opt<std::string>
-isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"),
- llvm::cl::desc("Set the system root directory (usually /)"));
-
-// Finally, implement the code that groks the options above.
-
-// Add the clang headers, which are relative to the clang binary.
-void AddClangIncludePaths(const char *Argv0, InitHeaderSearch *Init) {
- llvm::sys::Path MainExecutablePath =
- llvm::sys::Path::GetMainExecutable(Argv0,
- (void*)(intptr_t)AddClangIncludePaths);
- if (MainExecutablePath.isEmpty())
- return;
-
- MainExecutablePath.eraseComponent(); // Remove /clang from foo/bin/clang
- MainExecutablePath.eraseComponent(); // Remove /bin from foo/bin
-
- // Get foo/lib/clang/<version>/include
- MainExecutablePath.appendComponent("lib");
- MainExecutablePath.appendComponent("clang");
- MainExecutablePath.appendComponent(CLANG_VERSION_STRING);
- MainExecutablePath.appendComponent("include");
-
- // We pass true to ignore sysroot so that we *always* look for clang headers
- // relative to our executable, never relative to -isysroot.
- Init->AddPath(MainExecutablePath.c_str(), InitHeaderSearch::System,
- false, false, false, true /*ignore sysroot*/);
-}
-
-/// InitializeIncludePaths - Process the -I options and set them in the
-/// HeaderSearch object.
-void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,
- FileManager &FM, const LangOptions &Lang,
- llvm::Triple &triple) {
- InitHeaderSearch Init(Headers, Verbose, isysroot);
-
- // Handle -I... and -F... options, walking the lists in parallel.
- unsigned Iidx = 0, Fidx = 0;
- while (Iidx < I_dirs.size() && Fidx < F_dirs.size()) {
- if (I_dirs.getPosition(Iidx) < F_dirs.getPosition(Fidx)) {
- Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false);
- ++Iidx;
- } else {
- Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true);
- ++Fidx;
- }
- }
-
- // Consume what's left from whatever list was longer.
- for (; Iidx != I_dirs.size(); ++Iidx)
- Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false);
- for (; Fidx != F_dirs.size(); ++Fidx)
- Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true);
-
- // Handle -idirafter... options.
- for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i)
- Init.AddPath(idirafter_dirs[i], InitHeaderSearch::After,
- false, true, false);
-
- // Handle -iquote... options.
- for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i)
- Init.AddPath(iquote_dirs[i], InitHeaderSearch::Quoted, false, true, false);
-
- // Handle -isystem... options.
- for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i)
- Init.AddPath(isystem_dirs[i], InitHeaderSearch::System, false, true, false);
-
- // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in
- // parallel, processing the values in order of occurance to get the right
- // prefixes.
- {
- std::string Prefix = ""; // FIXME: this isn't the correct default prefix.
- unsigned iprefix_idx = 0;
- unsigned iwithprefix_idx = 0;
- unsigned iwithprefixbefore_idx = 0;
- bool iprefix_done = iprefix_vals.empty();
- bool iwithprefix_done = iwithprefix_vals.empty();
- bool iwithprefixbefore_done = iwithprefixbefore_vals.empty();
- while (!iprefix_done || !iwithprefix_done || !iwithprefixbefore_done) {
- if (!iprefix_done &&
- (iwithprefix_done ||
- iprefix_vals.getPosition(iprefix_idx) <
- iwithprefix_vals.getPosition(iwithprefix_idx)) &&
- (iwithprefixbefore_done ||
- iprefix_vals.getPosition(iprefix_idx) <
- iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
- Prefix = iprefix_vals[iprefix_idx];
- ++iprefix_idx;
- iprefix_done = iprefix_idx == iprefix_vals.size();
- } else if (!iwithprefix_done &&
- (iwithprefixbefore_done ||
- iwithprefix_vals.getPosition(iwithprefix_idx) <
- iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
- Init.AddPath(Prefix+iwithprefix_vals[iwithprefix_idx],
- InitHeaderSearch::System, false, false, false);
- ++iwithprefix_idx;
- iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size();
- } else {
- Init.AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx],
- InitHeaderSearch::Angled, false, false, false);
- ++iwithprefixbefore_idx;
- iwithprefixbefore_done =
- iwithprefixbefore_idx == iwithprefixbefore_vals.size();
- }
- }
- }
-
- Init.AddDefaultEnvVarPaths(Lang);
-
- if (!nobuiltininc)
- AddClangIncludePaths(Argv0, &Init);
-
- if (!nostdinc)
- Init.AddDefaultSystemIncludePaths(Lang, triple);
-
- // Now that we have collected all of the include paths, merge them all
- // together and tell the preprocessor about them.
-
- Init.Realize();
-}
-
-void InitializePreprocessorInitOptions(PreprocessorInitOptions &InitOpts) {
- // Use predefines?
- InitOpts.setUsePredefines(!UndefMacros);
-
- // Add macros from the command line.
- unsigned d = 0, D = D_macros.size();
- unsigned u = 0, U = U_macros.size();
- while (d < D || u < U) {
- if (u == U || (d < D && D_macros.getPosition(d) < U_macros.getPosition(u)))
- InitOpts.addMacroDef(D_macros[d++]);
- else
- InitOpts.addMacroUndef(U_macros[u++]);
- }
-
- // If -imacros are specified, include them now. These are processed before
- // any -include directives.
- for (unsigned i = 0, e = ImplicitMacroIncludes.size(); i != e; ++i)
- InitOpts.addMacroInclude(ImplicitMacroIncludes[i]);
-
- if (!ImplicitIncludePTH.empty() || !ImplicitIncludes.empty() ||
- (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput)) {
- // We want to add these paths to the predefines buffer in order, make a
- // temporary vector to sort by their occurrence.
- llvm::SmallVector<std::pair<unsigned, std::string*>, 8> OrderedPaths;
-
- if (!ImplicitIncludePTH.empty())
- OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(),
- &ImplicitIncludePTH));
- if (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput)
- OrderedPaths.push_back(std::make_pair(ImplicitIncludePCH.getPosition(),
- &ImplicitIncludePCH));
- for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i)
- OrderedPaths.push_back(std::make_pair(ImplicitIncludes.getPosition(i),
- &ImplicitIncludes[i]));
- llvm::array_pod_sort(OrderedPaths.begin(), OrderedPaths.end());
-
-
- // Now that they are ordered by position, add to the predefines buffer.
- for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i) {
- std::string *Ptr = OrderedPaths[i].second;
- if (!ImplicitIncludes.empty() &&
- Ptr >= &ImplicitIncludes[0] &&
- Ptr <= &ImplicitIncludes[ImplicitIncludes.size()-1]) {
- InitOpts.addInclude(*Ptr, false);
- } else if (Ptr == &ImplicitIncludePTH) {
- InitOpts.addInclude(*Ptr, true);
- } else {
- // We end up here when we're producing preprocessed output and
- // we loaded a PCH file. In this case, just include the header
- // file that was used to build the precompiled header.
- assert(Ptr == &ImplicitIncludePCH);
- std::string OriginalFile = PCHReader::getOriginalSourceFile(*Ptr);
- if (!OriginalFile.empty()) {
- InitOpts.addInclude(OriginalFile, false);
- ImplicitIncludePCH.clear();
- }
- }
- }
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Preprocessor construction
+// Main driver
//===----------------------------------------------------------------------===//
-static Preprocessor *
-CreatePreprocessor(Diagnostic &Diags,const LangOptions &LangInfo,
- TargetInfo &Target, SourceManager &SourceMgr,
- HeaderSearch &HeaderInfo) {
- PTHManager *PTHMgr = 0;
- if (!TokenCache.empty() && !ImplicitIncludePTH.empty()) {
- fprintf(stderr, "error: cannot use both -token-cache and -include-pth "
- "options\n");
- exit(1);
- }
-
- // Use PTH?
- if (!TokenCache.empty() || !ImplicitIncludePTH.empty()) {
- const std::string& x = TokenCache.empty() ? ImplicitIncludePTH:TokenCache;
- PTHMgr = PTHManager::Create(x, &Diags,
- TokenCache.empty() ? Diagnostic::Error
- : Diagnostic::Warning);
- }
-
- if (Diags.hasErrorOccurred())
- exit(1);
+std::string GetBuiltinIncludePath(const char *Argv0) {
+ llvm::sys::Path P =
+ llvm::sys::Path::GetMainExecutable(Argv0,
+ (void*)(intptr_t) GetBuiltinIncludePath);
- // Create the Preprocessor.
- Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
- SourceMgr, HeaderInfo, PTHMgr);
+ if (!P.isEmpty()) {
+ P.eraseComponent(); // Remove /clang from foo/bin/clang
+ P.eraseComponent(); // Remove /bin from foo/bin
- // Note that this is different then passing PTHMgr to Preprocessor's ctor.
- // That argument is used as the IdentifierInfoLookup argument to
- // IdentifierTable's ctor.
- if (PTHMgr) {
- PTHMgr->setPreprocessor(PP);
- PP->setPTHManager(PTHMgr);
+ // Get foo/lib/clang/<version>/include
+ P.appendComponent("lib");
+ P.appendComponent("clang");
+ P.appendComponent(CLANG_VERSION_STRING);
+ P.appendComponent("include");
}
- PreprocessorInitOptions InitOpts;
- InitializePreprocessorInitOptions(InitOpts);
- InitializePreprocessor(*PP, InitOpts);
-
- return PP;
+ return P.str();
}
-//===----------------------------------------------------------------------===//
-// Basic Parser driver
-//===----------------------------------------------------------------------===//
+static void LLVMErrorHandler(void *UserData, const std::string &Message) {
+ Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
-static void ParseFile(Preprocessor &PP, MinimalAction *PA) {
- Parser P(PP, *PA);
- PP.EnterMainSourceFile();
+ Diags.Report(diag::err_fe_error_backend) << Message;
- // Parsing the specified input file.
- P.ParseTranslationUnit();
- delete PA;
+ // We cannot recover from llvm errors.
+ exit(1);
}
-//===----------------------------------------------------------------------===//
-// Code generation options
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<bool>
-GenerateDebugInfo("g",
- llvm::cl::desc("Generate source level debug information"));
-
-static llvm::cl::opt<std::string>
-TargetCPU("mcpu",
- llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"));
-
-static llvm::cl::list<std::string>
-TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes"));
-
-
-static llvm::cl::opt<bool>
-DisableRedZone("disable-red-zone",
- llvm::cl::desc("Do not emit code that uses the red zone."),
- llvm::cl::init(false));
-
-static llvm::cl::opt<bool>
-NoImplicitFloat("no-implicit-float",
- llvm::cl::desc("Don't generate implicit floating point instructions (x86-only)"),
- llvm::cl::init(false));
-
-/// ComputeTargetFeatures - Recompute the target feature list to only
-/// be the list of things that are enabled, based on the target cpu
-/// and feature list.
-static void ComputeFeatureMap(TargetInfo *Target,
- llvm::StringMap<bool> &Features) {
- assert(Features.empty() && "invalid map");
-
- // Initialize the feature map based on the target.
- Target->getDefaultFeatures(TargetCPU, Features);
+/// ClangFrontendTimer - The front-end activities should charge time to it with
+/// TimeRegion. The -ftime-report option controls whether this will do
+/// anything.
+llvm::Timer *ClangFrontendTimer = 0;
- // Apply the user specified deltas.
- for (llvm::cl::list<std::string>::iterator it = TargetFeatures.begin(),
- ie = TargetFeatures.end(); it != ie; ++it) {
- const char *Name = it->c_str();
+static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
+ using namespace clang::frontend;
- // FIXME: Don't handle errors like this.
- if (Name[0] != '-' && Name[0] != '+') {
- fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n",
- Name);
- exit(1);
- }
- if (!Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
- fprintf(stderr, "error: clang-cc: invalid target feature name: %s\n",
- Name + 1);
+ switch (CI.getFrontendOpts().ProgramAction) {
+ default:
+ llvm::llvm_unreachable("Invalid program action!");
+
+ case ASTDump: return new ASTDumpAction();
+ case ASTPrint: return new ASTPrintAction();
+ case ASTPrintXML: return new ASTPrintXMLAction();
+ case ASTView: return new ASTViewAction();
+ case DumpRawTokens: return new DumpRawTokensAction();
+ case DumpRecordLayouts: return new DumpRecordAction();
+ case DumpTokens: return new DumpTokensAction();
+ case EmitAssembly: return new EmitAssemblyAction();
+ case EmitBC: return new EmitBCAction();
+ case EmitHTML: return new HTMLPrintAction();
+ case EmitLLVM: return new EmitLLVMAction();
+ case EmitLLVMOnly: return new EmitLLVMOnlyAction();
+ case FixIt: return new FixItAction();
+ case GeneratePCH: return new GeneratePCHAction();
+ case GeneratePTH: return new GeneratePTHAction();
+ case InheritanceView: return new InheritanceViewAction();
+ case ParseNoop: return new ParseOnlyAction();
+ case ParsePrintCallbacks: return new PrintParseAction();
+ case ParseSyntaxOnly: return new SyntaxOnlyAction();
+
+ case PluginAction: {
+ if (CI.getFrontendOpts().ActionName == "help") {
+ llvm::errs() << "clang-cc plugins:\n";
+ for (FrontendPluginRegistry::iterator it =
+ FrontendPluginRegistry::begin(),
+ ie = FrontendPluginRegistry::end();
+ it != ie; ++it)
+ llvm::errs() << " " << it->getName() << " - " << it->getDesc() << "\n";
exit(1);
}
- }
-}
-
-static void InitializeCompileOptions(CompileOptions &Opts,
- const LangOptions &LangOpts,
- const llvm::StringMap<bool> &Features) {
- Opts.OptimizeSize = OptSize;
- Opts.DebugInfo = GenerateDebugInfo;
- if (DisableLLVMOptimizations) {
- Opts.OptimizationLevel = 0;
- Opts.Inlining = CompileOptions::NoInlining;
- } else {
- if (OptSize) {
- // -Os implies -O2
- Opts.OptimizationLevel = 2;
- } else {
- Opts.OptimizationLevel = OptLevel;
+ for (FrontendPluginRegistry::iterator it =
+ FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
+ it != ie; ++it) {
+ if (it->getName() == CI.getFrontendOpts().ActionName)
+ return it->instantiate();
}
- // We must always run at least the always inlining pass.
- if (Opts.OptimizationLevel > 1)
- Opts.Inlining = CompileOptions::NormalInlining;
- else
- Opts.Inlining = CompileOptions::OnlyAlwaysInlining;
- }
-
- // FIXME: There are llvm-gcc options to control these selectively.
- Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !OptSize);
- Opts.SimplifyLibCalls = !LangOpts.NoBuiltin;
-
-#ifdef NDEBUG
- Opts.VerifyModule = 0;
-#endif
-
- Opts.CPU = TargetCPU;
- Opts.Features.clear();
- for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
- ie = Features.end(); it != ie; ++it) {
- // FIXME: If we are completely confident that we have the right
- // set, we only need to pass the minuses.
- std::string Name(it->second ? "+" : "-");
- Name += it->first();
- Opts.Features.push_back(Name);
- }
-
- Opts.NoCommon = NoCommon | LangOpts.CPlusPlus;
-
- // Handle -ftime-report.
- Opts.TimePasses = TimeReport;
-
- Opts.DisableRedZone = DisableRedZone;
- Opts.NoImplicitFloat = NoImplicitFloat;
-
- Opts.MergeAllConstants = !NoMergeConstants;
-}
-
-//===----------------------------------------------------------------------===//
-// Fix-It Options
-//===----------------------------------------------------------------------===//
-static llvm::cl::list<ParsedSourceLocation>
-FixItAtLocations("fixit-at", llvm::cl::value_desc("source-location"),
- llvm::cl::desc("Perform Fix-It modifications at the given source location"));
-
-//===----------------------------------------------------------------------===//
-// ObjC Rewriter Options
-//===----------------------------------------------------------------------===//
-static llvm::cl::opt<bool>
-SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::init(false),
- llvm::cl::desc("Silence ObjC rewriting warnings"));
-
-//===----------------------------------------------------------------------===//
-// Warning Options
-//===----------------------------------------------------------------------===//
-
-// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
-// driver has stripped off -Wa,foo etc. The driver has also translated -W to
-// -Wextra, so we don't need to worry about it.
-static llvm::cl::list<std::string>
-OptWarnings("W", llvm::cl::Prefix, llvm::cl::ValueOptional);
-
-static llvm::cl::opt<bool> OptPedantic("pedantic");
-static llvm::cl::opt<bool> OptPedanticErrors("pedantic-errors");
-static llvm::cl::opt<bool> OptNoWarnings("w");
-
-//===----------------------------------------------------------------------===//
-// Preprocessing (-E mode) Options
-//===----------------------------------------------------------------------===//
-static llvm::cl::opt<bool>
-DisableLineMarkers("P", llvm::cl::desc("Disable linemarker output in -E mode"));
-static llvm::cl::opt<bool>
-EnableCommentOutput("C", llvm::cl::desc("Enable comment output in -E mode"));
-static llvm::cl::opt<bool>
-EnableMacroCommentOutput("CC",
- llvm::cl::desc("Enable comment output in -E mode, "
- "even from macro expansions"));
-static llvm::cl::opt<bool>
-DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of"
- " normal output"));
-static llvm::cl::opt<bool>
-DumpDefines("dD", llvm::cl::desc("Print macro definitions in -E mode in "
- "addition to normal output"));
-
-//===----------------------------------------------------------------------===//
-// Dependency file options
-//===----------------------------------------------------------------------===//
-static llvm::cl::opt<std::string>
-DependencyFile("dependency-file",
- llvm::cl::desc("Filename (or -) to write dependency output to"));
-
-static llvm::cl::opt<bool>
-DependenciesIncludeSystemHeaders("sys-header-deps",
- llvm::cl::desc("Include system headers in dependency output"));
-
-static llvm::cl::list<std::string>
-DependencyTargets("MT",
- llvm::cl::desc("Specify target for dependency"));
-
-// FIXME: Implement feature
-static llvm::cl::opt<bool>
-PhonyDependencyTarget("MP",
- llvm::cl::desc("Create phony target for each dependency "
- "(other than main file)"));
-
-//===----------------------------------------------------------------------===//
-// Analysis options
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::list<Analyses>
-AnalysisList(llvm::cl::desc("Source Code Analysis - Checks and Analyses"),
-llvm::cl::values(
-#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
-clEnumValN(NAME, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<AnalysisStores>
-AnalysisStoreOpt("analyzer-store",
- llvm::cl::desc("Source Code Analysis - Abstract Memory Store Models"),
- llvm::cl::init(BasicStoreModel),
- llvm::cl::values(
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)\
-clEnumValN(NAME##Model, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<AnalysisConstraints>
-AnalysisConstraintsOpt("analyzer-constraints",
- llvm::cl::desc("Source Code Analysis - Symbolic Constraint Engines"),
- llvm::cl::init(RangeConstraintsModel),
- llvm::cl::values(
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)\
-clEnumValN(NAME##Model, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<AnalysisDiagClients>
-AnalysisDiagOpt("analyzer-output",
- llvm::cl::desc("Source Code Analysis - Output Options"),
- llvm::cl::init(PD_HTML),
- llvm::cl::values(
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE)\
-clEnumValN(PD_##NAME, CMDFLAG, DESC),
-#include "clang/Frontend/Analyses.def"
-clEnumValEnd));
-
-static llvm::cl::opt<bool>
-VisualizeEGDot("analyzer-viz-egraph-graphviz",
- llvm::cl::desc("Display exploded graph using GraphViz"));
-
-static llvm::cl::opt<bool>
-VisualizeEGUbi("analyzer-viz-egraph-ubigraph",
- llvm::cl::desc("Display exploded graph using Ubigraph"));
-
-static llvm::cl::opt<bool>
-AnalyzeAll("analyzer-opt-analyze-headers",
- llvm::cl::desc("Force the static analyzer to analyze "
- "functions defined in header files"));
-
-static llvm::cl::opt<bool>
-AnalyzerDisplayProgress("analyzer-display-progress",
- llvm::cl::desc("Emit verbose output about the analyzer's progress."));
-
-static llvm::cl::opt<bool>
-PurgeDead("analyzer-purge-dead",
- llvm::cl::init(true),
- llvm::cl::desc("Remove dead symbols, bindings, and constraints before"
- " processing a statement."));
-
-static llvm::cl::opt<bool>
-EagerlyAssume("analyzer-eagerly-assume",
- llvm::cl::init(false),
- llvm::cl::desc("Eagerly assume the truth/falseness of some "
- "symbolic constraints."));
-
-static llvm::cl::opt<std::string>
-AnalyzeSpecificFunction("analyze-function",
- llvm::cl::desc("Run analysis on specific function"));
-
-static llvm::cl::opt<bool>
-TrimGraph("trim-egraph",
- llvm::cl::desc("Only show error-related paths in the analysis graph"));
-
-static AnalyzerOptions ReadAnalyzerOptions() {
- AnalyzerOptions Opts;
- Opts.AnalysisList = AnalysisList;
- Opts.AnalysisStoreOpt = AnalysisStoreOpt;
- Opts.AnalysisConstraintsOpt = AnalysisConstraintsOpt;
- Opts.AnalysisDiagOpt = AnalysisDiagOpt;
- Opts.VisualizeEGDot = VisualizeEGDot;
- Opts.VisualizeEGUbi = VisualizeEGUbi;
- Opts.AnalyzeAll = AnalyzeAll;
- Opts.AnalyzerDisplayProgress = AnalyzerDisplayProgress;
- Opts.PurgeDead = PurgeDead;
- Opts.EagerlyAssume = EagerlyAssume;
- Opts.AnalyzeSpecificFunction = AnalyzeSpecificFunction;
- Opts.TrimGraph = TrimGraph;
- return Opts;
-}
-
-//===----------------------------------------------------------------------===//
-// -dump-build-information Stuff
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<std::string>
-DumpBuildInformation("dump-build-information",
- llvm::cl::value_desc("filename"),
- llvm::cl::desc("output a dump of some build information to a file"));
-
-static llvm::raw_ostream *BuildLogFile = 0;
-
-/// LoggingDiagnosticClient - This is a simple diagnostic client that forwards
-/// all diagnostics to both BuildLogFile and a chained DiagnosticClient.
-namespace {
-class LoggingDiagnosticClient : public DiagnosticClient {
- llvm::OwningPtr<DiagnosticClient> Chain1;
- llvm::OwningPtr<DiagnosticClient> Chain2;
-public:
-
- LoggingDiagnosticClient(DiagnosticClient *Normal) {
- // Output diags both where requested...
- Chain1.reset(Normal);
- // .. and to our log file.
- Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, DiagOpts));
- }
-
- virtual void BeginSourceFile(const LangOptions &LO) {
- Chain1->BeginSourceFile(LO);
- Chain2->BeginSourceFile(LO);
- }
-
- virtual void EndSourceFile() {
- Chain1->EndSourceFile();
- Chain2->EndSourceFile();
- }
-
- virtual bool IncludeInDiagnosticCounts() const {
- return Chain1->IncludeInDiagnosticCounts();
- }
-
- virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
- const DiagnosticInfo &Info) {
- Chain1->HandleDiagnostic(DiagLevel, Info);
- Chain2->HandleDiagnostic(DiagLevel, Info);
- }
-};
-} // end anonymous namespace.
-
-static void SetUpBuildDumpLog(unsigned argc, char **argv,
- llvm::OwningPtr<DiagnosticClient> &DiagClient) {
-
- std::string ErrorInfo;
- BuildLogFile = new llvm::raw_fd_ostream(DumpBuildInformation.c_str(),
- ErrorInfo);
-
- if (!ErrorInfo.empty()) {
- llvm::errs() << "error opening -dump-build-information file '"
- << DumpBuildInformation << "', option ignored!\n";
- delete BuildLogFile;
- BuildLogFile = 0;
- DumpBuildInformation = "";
- return;
- }
-
- (*BuildLogFile) << "clang-cc command line arguments: ";
- for (unsigned i = 0; i != argc; ++i)
- (*BuildLogFile) << argv[i] << ' ';
- (*BuildLogFile) << '\n';
-
- // LoggingDiagnosticClient - Insert a new logging diagnostic client in between
- // the diagnostic producers and the normal receiver.
- DiagClient.reset(new LoggingDiagnosticClient(DiagClient.take()));
-}
-
-
-
-//===----------------------------------------------------------------------===//
-// Main driver
-//===----------------------------------------------------------------------===//
-
-static llvm::raw_ostream *ComputeOutFile(const std::string &InFile,
- const char *Extension,
- bool Binary,
- llvm::sys::Path& OutPath) {
- llvm::raw_ostream *Ret;
- std::string OutFile;
- if (!OutputFile.empty())
- OutFile = OutputFile;
- else if (InFile == "-") {
- OutFile = "-";
- } else if (Extension) {
- llvm::sys::Path Path(InFile);
- Path.eraseSuffix();
- Path.appendSuffix(Extension);
- OutFile = Path.str();
- } else {
- OutFile = "-";
- }
-
- std::string Error;
- Ret = new llvm::raw_fd_ostream(OutFile.c_str(), Error,
- (Binary ? llvm::raw_fd_ostream::F_Binary : 0));
- if (!Error.empty()) {
- // FIXME: Don't fail this way.
- llvm::errs() << "ERROR: " << Error << "\n";
- ::exit(1);
- }
-
- if (OutFile != "-")
- OutPath = OutFile;
-
- return Ret;
-}
-
-static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
- const std::string &InFile,
- ProgActions PA,
- llvm::OwningPtr<llvm::raw_ostream> &OS,
- llvm::sys::Path &OutPath,
- const llvm::StringMap<bool> &Features,
- llvm::LLVMContext& Context) {
- switch (PA) {
- default:
+ CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
+ << CI.getFrontendOpts().ActionName;
return 0;
-
- case ASTPrint:
- OS.reset(ComputeOutFile(InFile, 0, false, OutPath));
- return CreateASTPrinter(OS.get());
-
- case ASTPrintXML:
- OS.reset(ComputeOutFile(InFile, "xml", false, OutPath));
- return CreateASTPrinterXML(OS.get());
-
- case ASTDump:
- return CreateASTDumper();
-
- case ASTView:
- return CreateASTViewer();
-
- case PrintDeclContext:
- return CreateDeclContextPrinter();
-
- case DumpRecordLayouts:
- return CreateRecordLayoutDumper();
-
- case InheritanceView:
- return CreateInheritanceViewer(InheritanceViewCls);
-
- case EmitAssembly:
- case EmitLLVM:
- case EmitBC:
- case EmitLLVMOnly: {
- BackendAction Act;
- if (ProgAction == EmitAssembly) {
- Act = Backend_EmitAssembly;
- OS.reset(ComputeOutFile(InFile, "s", true, OutPath));
- } else if (ProgAction == EmitLLVM) {
- Act = Backend_EmitLL;
- OS.reset(ComputeOutFile(InFile, "ll", true, OutPath));
- } else if (ProgAction == EmitLLVMOnly) {
- Act = Backend_EmitNothing;
- } else {
- Act = Backend_EmitBC;
- OS.reset(ComputeOutFile(InFile, "bc", true, OutPath));
- }
-
- CompileOptions Opts;
- InitializeCompileOptions(Opts, PP.getLangOptions(), Features);
- return CreateBackendConsumer(Act, PP.getDiagnostics(), PP.getLangOptions(),
- Opts, InFile, OS.get(), Context);
}
- case RewriteObjC:
- OS.reset(ComputeOutFile(InFile, "cpp", true, OutPath));
- return CreateObjCRewriter(InFile, OS.get(), PP.getDiagnostics(),
- PP.getLangOptions(), SilenceRewriteMacroWarning);
-
- case RewriteBlocks:
- return CreateBlockRewriter(InFile, PP.getDiagnostics(),
- PP.getLangOptions());
+ case PrintDeclContext: return new DeclContextPrintAction();
+ case PrintPreprocessedInput: return new PrintPreprocessedAction();
+ case RewriteBlocks: return new RewriteBlocksAction();
+ case RewriteMacros: return new RewriteMacrosAction();
+ case RewriteObjC: return new RewriteObjCAction();
+ case RewriteTest: return new RewriteTestAction();
+ case RunAnalysis: return new AnalysisAction();
+ case RunPreprocessorOnly: return new PreprocessOnlyAction();
}
}
-/// ProcessInputFile - Process a single input file with the specified state.
-///
-static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
- ProgActions PA,
- const llvm::StringMap<bool> &Features,
- llvm::LLVMContext& Context) {
- llvm::OwningPtr<llvm::raw_ostream> OS;
- llvm::OwningPtr<ASTConsumer> Consumer;
- bool ClearSourceMgr = false;
- FixItRewriter *FixItRewrite = 0;
- bool CompleteTranslationUnit = true;
- llvm::sys::Path OutPath;
-
- switch (PA) {
- default:
- Consumer.reset(CreateConsumerAction(PP, InFile, PA, OS, OutPath,
- Features, Context));
-
- if (!Consumer.get()) {
- PP.getDiagnostics().Report(FullSourceLoc(),
- diag::err_fe_invalid_ast_action);
- return;
- }
-
- break;;
-
- case EmitHTML:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- Consumer.reset(CreateHTMLPrinter(OS.get(), PP));
- break;
-
- case RunAnalysis:
- Consumer.reset(CreateAnalysisConsumer(PP, OutputFile,
- ReadAnalyzerOptions()));
- break;
-
- case GeneratePCH:
- if (RelocatablePCH.getValue() && !isysroot.getNumOccurrences()) {
- PP.Diag(SourceLocation(), diag::err_relocatable_without_without_isysroot);
- RelocatablePCH.setValue(false);
- }
-
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- if (RelocatablePCH.getValue())
- Consumer.reset(CreatePCHGenerator(PP, OS.get(), isysroot.c_str()));
- else
- Consumer.reset(CreatePCHGenerator(PP, OS.get()));
- CompleteTranslationUnit = false;
- break;
+static TargetInfo *
+ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags,
+ const char *Argv0, bool &IsAST) {
+ // Initialize target options.
+ InitializeTargetOptions(Opts.getTargetOpts());
- case DumpRawTokens: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- SourceManager &SM = PP.getSourceManager();
- // Start lexing the specified input file.
- Lexer RawLex(SM.getMainFileID(), SM, PP.getLangOptions());
- RawLex.SetKeepWhitespaceMode(true);
-
- Token RawTok;
- RawLex.LexFromRawLexer(RawTok);
- while (RawTok.isNot(tok::eof)) {
- PP.DumpToken(RawTok, true);
- fprintf(stderr, "\n");
- RawLex.LexFromRawLexer(RawTok);
- }
- ClearSourceMgr = true;
- break;
- }
- case DumpTokens: { // Token dump mode.
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Token Tok;
- // Start preprocessing the specified input file.
- PP.EnterMainSourceFile();
- do {
- PP.Lex(Tok);
- PP.DumpToken(Tok, true);
- fprintf(stderr, "\n");
- } while (Tok.isNot(tok::eof));
- ClearSourceMgr = true;
- break;
- }
- case RunPreprocessorOnly:
- break;
-
- case GeneratePTH: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- if (OutputFile.empty() || OutputFile == "-") {
- // FIXME: Don't fail this way.
- // FIXME: Verify that we can actually seek in the given file.
- llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
- ::exit(1);
- }
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- CacheTokens(PP, static_cast<llvm::raw_fd_ostream*>(OS.get()));
- ClearSourceMgr = true;
- break;
- }
-
- case PrintPreprocessedInput:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- break;
-
- case ParseNoop:
- break;
-
- case ParsePrintCallbacks: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- ParseFile(PP, CreatePrintParserActionsAction(PP, OS.get()));
- ClearSourceMgr = true;
- break;
- }
-
- case ParseSyntaxOnly: { // -fsyntax-only
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Consumer.reset(new ASTConsumer());
- break;
- }
-
- case RewriteMacros:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- RewriteMacrosInInput(PP, OS.get());
- ClearSourceMgr = true;
- break;
-
- case RewriteTest:
- OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- DoRewriteTest(PP, OS.get());
- ClearSourceMgr = true;
- break;
-
- case FixIt:
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Consumer.reset(new ASTConsumer());
- FixItRewrite = new FixItRewriter(PP.getDiagnostics(),
- PP.getSourceManager(),
- PP.getLangOptions());
- break;
- }
-
- if (FixItAtLocations.size() > 0) {
- // Even without the "-fixit" flag, with may have some specific
- // locations where the user has requested fixes. Process those
- // locations now.
- if (!FixItRewrite)
- FixItRewrite = new FixItRewriter(PP.getDiagnostics(),
- PP.getSourceManager(),
- PP.getLangOptions());
-
- bool AddedFixitLocation = false;
- for (unsigned Idx = 0, Last = FixItAtLocations.size();
- Idx != Last; ++Idx) {
- RequestedSourceLocation Requested;
- if (ResolveParsedLocation(FixItAtLocations[Idx],
- PP.getFileManager(), Requested)) {
- fprintf(stderr, "FIX-IT could not find file \"%s\"\n",
- FixItAtLocations[Idx].FileName.c_str());
- } else {
- FixItRewrite->addFixItLocation(Requested);
- AddedFixitLocation = true;
- }
- }
-
- if (!AddedFixitLocation) {
- // All of the fix-it locations were bad. Don't fix anything.
- delete FixItRewrite;
- FixItRewrite = 0;
- }
- }
-
- llvm::OwningPtr<ASTContext> ContextOwner;
- if (Consumer)
- ContextOwner.reset(new ASTContext(PP.getLangOptions(),
- PP.getSourceManager(),
- PP.getTargetInfo(),
- PP.getIdentifierTable(),
- PP.getSelectorTable(),
- PP.getBuiltinInfo(),
- /* FreeMemory = */ !DisableFree,
- /* size_reserve = */0));
-
- llvm::OwningPtr<PCHReader> Reader;
- llvm::OwningPtr<ExternalASTSource> Source;
-
- if (!ImplicitIncludePCH.empty()) {
- // If the user specified -isysroot, it will be used for relocatable PCH
- // files.
- const char *isysrootPCH = 0;
- if (isysroot.getNumOccurrences() != 0)
- isysrootPCH = isysroot.c_str();
-
- Reader.reset(new PCHReader(PP, ContextOwner.get(), isysrootPCH));
-
- // The user has asked us to include a precompiled header. Load
- // the precompiled header into the AST context.
- switch (Reader->ReadPCH(ImplicitIncludePCH)) {
- case PCHReader::Success: {
- // Set the predefines buffer as suggested by the PCH
- // reader. Typically, the predefines buffer will be empty.
- PP.setPredefines(Reader->getSuggestedPredefines());
-
- // Attach the PCH reader to the AST context as an external AST
- // source, so that declarations will be deserialized from the
- // PCH file as needed.
- if (ContextOwner) {
- Source.reset(Reader.take());
- ContextOwner->setExternalSource(Source);
- }
- break;
- }
-
- case PCHReader::Failure:
- // Unrecoverable failure: don't even try to process the input
- // file.
- return;
-
- case PCHReader::IgnorePCH:
- // No suitable PCH file could be found. Return an error.
- return;
-
-#if 0
- // FIXME: We can recover from failed attempts to load PCH
- // files. This code will do so, if we ever want to enable it.
-
- // We delayed the initialization of builtins in the hope of
- // loading the PCH file. Since the PCH file could not be
- // loaded, initialize builtins now.
- if (ContextOwner)
- ContextOwner->InitializeBuiltins(PP.getIdentifierTable());
-#endif
- }
-
- // Finish preprocessor initialization. We do this now (rather
- // than earlier) because this initialization creates new source
- // location entries in the source manager, which must come after
- // the source location entries for the PCH file.
- if (InitializeSourceManager(PP, InFile))
- return;
- }
-
- // If we have an ASTConsumer, run the parser with it.
- if (Consumer) {
- CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *) = 0;
- void *CreateCodeCompleterData = 0;
+ // Get information about the target being compiled for.
+ llvm::OwningPtr<TargetInfo> Target(
+ TargetInfo::CreateTargetInfo(Diags, Opts.getTargetOpts()));
+ if (!Target)
+ return 0;
- if (!CodeCompletionAt.FileName.empty()) {
- // Tell the source manager to chop off the given file at a specific
- // line and column.
- if (const FileEntry *Entry
- = PP.getFileManager().getFile(CodeCompletionAt.FileName)) {
- // Truncate the named file at the given line/column.
- PP.getSourceManager().truncateFileAt(Entry, CodeCompletionAt.Line,
- CodeCompletionAt.Column);
+ // Initialize frontend options.
+ InitializeFrontendOptions(Opts.getFrontendOpts());
- // Set up the creation routine for code-completion.
- CreateCodeCompleter = BuildPrintingCodeCompleter;
- } else {
- PP.getDiagnostics().Report(FullSourceLoc(),
- diag::err_fe_invalid_code_complete_file)
- << CodeCompletionAt.FileName;
- }
+ // Determine the input language, we currently require all files to match.
+ FrontendOptions::InputKind IK = Opts.getFrontendOpts().Inputs[0].first;
+ for (unsigned i = 1, e = Opts.getFrontendOpts().Inputs.size(); i != e; ++i) {
+ if (Opts.getFrontendOpts().Inputs[i].first != IK) {
+ llvm::errs() << "error: cannot have multiple input files of distinct "
+ << "language kinds without -x\n";
+ return 0;
}
-
- ParseAST(PP, Consumer.get(), *ContextOwner.get(), Stats,
- CompleteTranslationUnit,
- CreateCodeCompleter, CreateCodeCompleterData);
}
- // Perform post processing actions and actions which don't use a consumer.
- switch (PA) {
- default: break;
-
- case RunPreprocessorOnly: { // Just lex as fast as we can, no output.
- llvm::TimeRegion Timer(ClangFrontendTimer);
- Token Tok;
- // Start parsing the specified input file.
- PP.EnterMainSourceFile();
- do {
- PP.Lex(Tok);
- } while (Tok.isNot(tok::eof));
- ClearSourceMgr = true;
- break;
- }
-
- case ParseNoop: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- ParseFile(PP, new MinimalAction(PP));
- ClearSourceMgr = true;
- break;
- }
-
- case PrintPreprocessedInput: {
- llvm::TimeRegion Timer(ClangFrontendTimer);
- if (DumpMacros)
- DoPrintMacros(PP, OS.get());
- else
- DoPrintPreprocessedInput(PP, OS.get(), EnableCommentOutput,
- EnableMacroCommentOutput,
- DisableLineMarkers, DumpDefines);
- ClearSourceMgr = true;
- }
-
- }
-
- if (FixItRewrite)
- FixItRewrite->WriteFixedFile(InFile, OutputFile);
-
- // Disable the consumer prior to the context, the consumer may perform actions
- // in its destructor which require the context.
- if (DisableFree)
- Consumer.take();
- else
- Consumer.reset();
-
- // If in -disable-free mode, don't deallocate ASTContext.
- if (DisableFree)
- ContextOwner.take();
- else
- ContextOwner.reset(); // Delete ASTContext
-
- if (VerifyDiagnostics)
- if (CheckDiagnostics(PP))
- exit(1);
-
- if (Stats) {
- fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str());
- PP.PrintStats();
- PP.getIdentifierTable().PrintStats();
- PP.getHeaderSearchInfo().PrintStats();
- PP.getSourceManager().PrintStats();
- fprintf(stderr, "\n");
- }
-
- // For a multi-file compilation, some things are ok with nuking the source
- // manager tables, other require stable fileid/macroid's across multiple
- // files.
- if (ClearSourceMgr)
- PP.getSourceManager().clearIDTables();
-
- // Always delete the output stream because we don't want to leak file
- // handles. Also, we don't want to try to erase an open file.
- OS.reset();
-
- // If we had errors, try to erase the output file.
- if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
- OutPath.eraseFromDisk();
-}
-
-/// ProcessInputFile - Process a single AST input file with the specified state.
-///
-static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,
- const llvm::StringMap<bool> &Features,
- Diagnostic &Diags, FileManager &FileMgr,
- llvm::LLVMContext& Context) {
- std::string Error;
- llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, &Error));
- if (!AST) {
- Diags.Report(FullSourceLoc(), diag::err_fe_invalid_ast_file) << Error;
- return;
- }
-
- Preprocessor &PP = AST->getPreprocessor();
-
- llvm::OwningPtr<llvm::raw_ostream> OS;
- llvm::sys::Path OutPath;
- llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(PP, InFile, PA, OS,
- OutPath, Features,
- Context));
-
- if (!Consumer.get()) {
- Diags.Report(FullSourceLoc(), diag::err_fe_invalid_ast_action);
- return;
- }
-
- // Set the main file ID to an empty file.
+ // Initialize language options.
//
- // FIXME: We probably shouldn't need this, but for now this is the simplest
- // way to reuse the logic in ParseAST.
- const char *EmptyStr = "";
- llvm::MemoryBuffer *SB =
- llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>");
- AST->getSourceManager().createMainFileIDForMemBuffer(SB);
-
- // Stream the input AST to the consumer.
- Diags.getClient()->BeginSourceFile(PP.getLangOptions());
- ParseAST(PP, Consumer.get(), AST->getASTContext(), Stats);
- Diags.getClient()->EndSourceFile();
+ // FIXME: These aren't used during operations on ASTs. Split onto a separate
+ // code path to make this obvious.
+ IsAST = (IK == FrontendOptions::IK_AST);
+ if (!IsAST)
+ InitializeLangOptions(Opts.getLangOpts(), IK, *Target);
- // Release the consumer and the AST, in that order since the consumer may
- // perform actions in its destructor which require the context.
- if (DisableFree) {
- Consumer.take();
- AST.take();
- } else {
- Consumer.reset();
- AST.reset();
- }
+ // Initialize the static analyzer options.
+ InitializeAnalyzerOptions(Opts.getAnalyzerOpts());
- // Always delete the output stream because we don't want to leak file
- // handles. Also, we don't want to try to erase an open file.
- OS.reset();
+ // Initialize the dependency output options (-M...).
+ InitializeDependencyOutputOptions(Opts.getDependencyOutputOpts());
- // If we had errors, try to erase the output file.
- if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
- OutPath.eraseFromDisk();
-}
+ // Initialize the header search options.
+ InitializeHeaderSearchOptions(Opts.getHeaderSearchOpts(),
+ GetBuiltinIncludePath(Argv0));
-static llvm::cl::list<std::string>
-InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
+ // Initialize the other preprocessor options.
+ InitializePreprocessorOptions(Opts.getPreprocessorOpts());
-static void LLVMErrorHandler(void *UserData, const std::string &Message) {
- Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
+ // Initialize the preprocessed output options.
+ InitializePreprocessorOutputOptions(Opts.getPreprocessorOutputOpts());
- Diags.Report(FullSourceLoc(), diag::err_fe_error_backend) << Message;
+ // Initialize backend options, which may also be used to key some language
+ // options.
+ InitializeCodeGenOptions(Opts.getCodeGenOpts(), Opts.getLangOpts(),
+ Opts.getFrontendOpts().ShowTimers);
- // We cannot recover from llvm errors.
- exit(1);
+ return Target.take();
}
int main(int argc, char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
- llvm::LLVMContext &Context = llvm::getGlobalContext();
+ CompilerInstance Clang(&llvm::getGlobalContext(), false);
// Initialize targets first, so that --version shows registered targets.
llvm::InitializeAllTargets();
@@ -2132,183 +208,102 @@ int main(int argc, char **argv) {
llvm::cl::ParseCommandLineOptions(argc, argv,
"LLVM 'Clang' Compiler: http://clang.llvm.org\n");
- if (TimeReport)
- ClangFrontendTimer = new llvm::Timer("Clang front-end time");
-
- if (Verbose)
- llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
- << " based upon " << PACKAGE_STRING
- << " hosted on " << llvm::sys::getHostTriple() << "\n";
-
- // If no input was specified, read from stdin.
- if (InputFilenames.empty())
- InputFilenames.push_back("-");
-
- // Initialize the diagnostic options.
- DiagOpts.ShowColumn = !NoShowColumn;
- DiagOpts.ShowLocation = !NoShowLocation;
- DiagOpts.ShowCarets = !NoCaretDiagnostics;
- DiagOpts.ShowFixits = !NoDiagnosticsFixIt;
- DiagOpts.ShowSourceRanges = PrintSourceRangeInfo;
- DiagOpts.ShowOptionNames = PrintDiagnosticOption;
- DiagOpts.ShowColors = PrintColorDiagnostic;
- DiagOpts.MessageLength = MessageLength;
-
- // Create the diagnostic client for reporting errors or for
- // implementing -verify.
- llvm::OwningPtr<DiagnosticClient> DiagClient;
- if (VerifyDiagnostics) {
- // When checking diagnostics, just buffer them up.
- DiagClient.reset(new TextDiagnosticBuffer());
- if (InputFilenames.size() != 1) {
- fprintf(stderr, "-verify only works on single input files for now.\n");
- return 1;
- }
- } else {
- DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
- }
-
- if (!DumpBuildInformation.empty())
- SetUpBuildDumpLog(argc, argv, DiagClient);
-
- // Configure our handling of diagnostics.
- Diagnostic Diags(DiagClient.get());
- if (ProcessWarningOptions(Diags, OptWarnings, OptPedantic, OptPedanticErrors,
- OptNoWarnings))
+ // Construct the diagnostic engine first, so that we can build a diagnostic
+ // client to use for any errors during option handling.
+ InitializeDiagnosticOptions(Clang.getDiagnosticOpts());
+ Clang.createDiagnostics(argc, argv);
+ if (!Clang.hasDiagnostics())
return 1;
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.
llvm::llvm_install_error_handler(LLVMErrorHandler,
- static_cast<void*>(&Diags));
-
- // Initialize base triple. If a -triple option has been specified, use
- // that triple. Otherwise, default to the host triple.
- llvm::Triple Triple(TargetTriple);
- if (Triple.getTriple().empty())
- Triple = llvm::Triple(llvm::sys::getHostTriple());
+ static_cast<void*>(&Clang.getDiagnostics()));
- // Get information about the target being compiled for.
- llvm::OwningPtr<TargetInfo>
- Target(TargetInfo::CreateTargetInfo(Triple.getTriple()));
-
- if (Target == 0) {
- Diags.Report(FullSourceLoc(), diag::err_fe_unknown_triple)
- << Triple.getTriple().c_str();
+ // Now that we have initialized the diagnostics engine, create the target and
+ // the compiler invocation object.
+ //
+ // FIXME: We should move .ast inputs to taking a separate path, they are
+ // really quite different.
+ bool IsAST = false;
+ Clang.setTarget(
+ ConstructCompilerInvocation(Clang.getInvocation(), Clang.getDiagnostics(),
+ argv[0], IsAST));
+ if (!Clang.hasTarget())
return 1;
- }
-
- // Set the target ABI if specified.
- if (!TargetABI.empty()) {
- if (!Target->setABI(TargetABI)) {
- Diags.Report(FullSourceLoc(), diag::err_fe_unknown_target_abi)
- << TargetABI;
- return 1;
- }
- }
-
- if (!InheritanceViewCls.empty()) // C++ visualization?
- ProgAction = InheritanceView;
-
- // Create the source manager.
- SourceManager SourceMgr;
-
- // Create a file manager object to provide access to and cache the filesystem.
- FileManager FileMgr;
-
- // Compute the feature set, unfortunately this effects the language!
- llvm::StringMap<bool> Features;
- ComputeFeatureMap(Target.get(), Features);
-
- for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
- const std::string &InFile = InputFilenames[i];
-
- LangKind LK = GetLanguage(InFile);
- // AST inputs are handled specially.
- if (LK == langkind_ast) {
- ProcessASTInputFile(InFile, ProgAction, Features,
- Diags, FileMgr, Context);
- continue;
- }
-
- // Reset the ID tables if we are reusing the SourceManager.
- if (i)
- SourceMgr.clearIDTables();
-
- // Initialize language options, inferring file types from input filenames.
- LangOptions LangInfo;
- InitializeLangOptions(LangInfo, LK);
- InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
-
- // Process the -I options and set them in the HeaderInfo.
- HeaderSearch HeaderInfo(FileMgr);
-
-
- InitializeIncludePaths(argv[0], HeaderInfo, FileMgr, LangInfo, Triple);
+ // Validate/process some options
+ if (Clang.getHeaderSearchOpts().Verbose)
+ llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
+ << " based upon " << PACKAGE_STRING
+ << " hosted on " << llvm::sys::getHostTriple() << "\n";
- // Set up the preprocessor with these options.
- llvm::OwningPtr<Preprocessor> PP(CreatePreprocessor(Diags, LangInfo,
- *Target, SourceMgr,
- HeaderInfo));
+ if (Clang.getFrontendOpts().ShowTimers)
+ ClangFrontendTimer = new llvm::Timer("Clang front-end time");
- // Handle generating dependencies, if requested.
- if (!DependencyFile.empty()) {
- if (DependencyTargets.empty()) {
- Diags.Report(FullSourceLoc(), diag::err_fe_dependency_file_requires_MT);
- continue;
- }
- std::string ErrStr;
- llvm::raw_ostream *DependencyOS =
- new llvm::raw_fd_ostream(DependencyFile.c_str(), ErrStr);
- if (!ErrStr.empty()) {
- Diags.Report(FullSourceLoc(), diag::err_fe_error_opening)
- << DependencyFile << ErrStr;
- continue;
+ // Enforce certain implications.
+ if (!Clang.getFrontendOpts().ViewClassInheritance.empty())
+ Clang.getFrontendOpts().ProgramAction = frontend::InheritanceView;
+ if (!Clang.getFrontendOpts().FixItLocations.empty())
+ Clang.getFrontendOpts().ProgramAction = frontend::FixIt;
+
+ for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
+ const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;
+
+ // If we aren't using an AST file, setup the file and source managers and
+ // the preprocessor.
+ if (!IsAST) {
+ if (!i) {
+ // Create a file manager object to provide access to and cache the
+ // filesystem.
+ Clang.createFileManager();
+
+ // Create the source manager.
+ Clang.createSourceManager();
+ } else {
+ // Reset the ID tables if we are reusing the SourceManager.
+ Clang.getSourceManager().clearIDTables();
}
- AttachDependencyFileGen(PP.get(), DependencyOS, DependencyTargets,
- DependenciesIncludeSystemHeaders,
- PhonyDependencyTarget);
+ // Create the preprocessor.
+ Clang.createPreprocessor();
}
- if (ImplicitIncludePCH.empty()) {
- if (InitializeSourceManager(*PP.get(), InFile))
- continue;
+ llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
+ if (!Act)
+ break;
- // Initialize builtin info.
- PP->getBuiltinInfo().InitializeBuiltins(PP->getIdentifierTable(),
- PP->getLangOptions().NoBuiltin);
+ Act->setCurrentTimer(ClangFrontendTimer);
+ if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
+ Act->Execute();
+ Act->EndSourceFile();
}
-
- // Process the source file.
- DiagClient->BeginSourceFile(LangInfo);
- ProcessInputFile(*PP, InFile, ProgAction, Features, Context);
- DiagClient->EndSourceFile();
-
- HeaderInfo.ClearFileInfo();
}
- if (!NoCaretDiagnostics)
- if (unsigned NumDiagnostics = Diags.getNumDiagnostics())
+ if (Clang.getDiagnosticOpts().ShowCarets)
+ if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics())
fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
(NumDiagnostics == 1 ? "" : "s"));
- if (Stats) {
- FileMgr.PrintStats();
+ if (Clang.getFrontendOpts().ShowStats) {
+ Clang.getFileManager().PrintStats();
fprintf(stderr, "\n");
}
delete ClangFrontendTimer;
- delete BuildLogFile;
- // If verifying diagnostics and we reached here, all is well.
- if (VerifyDiagnostics)
- return 0;
+ // Return the appropriate status when verifying diagnostics.
+ //
+ // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
+ // this.
+ if (Clang.getDiagnosticOpts().VerifyDiagnostics)
+ return static_cast<VerifyDiagnosticsClient&>(
+ Clang.getDiagnosticClient()).HadErrors();
// Managed static deconstruction. Useful for making things like
// -time-passes usable.
llvm::llvm_shutdown();
- return (Diags.getNumErrors() != 0);
+ return (Clang.getDiagnostics().getNumErrors() != 0);
}
+
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 9d204ce6c0c2..fb7c6cc7b032 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -197,6 +197,16 @@ int main(int argc, const char **argv) {
llvm::sys::getHostTriple().c_str(),
"a.out", IsProduction, Diags);
+ // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
+ // compiler. This matches things like "c++", "clang++", and "clang++-1.1".
+ //
+ // Note that we intentionally want to use argv[0] here, to support "clang++"
+ // being a symlink.
+ std::string ProgName(llvm::sys::Path(argv[0]).getBasename());
+ if (llvm::StringRef(ProgName).endswith("++") ||
+ llvm::StringRef(ProgName).rsplit('-').first.endswith("++"))
+ TheDriver.CCCIsCXX = true;
+
llvm::OwningPtr<Compilation> C;
// Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
diff --git a/utils/C++Tests/Clang-Code-Compile/lit.local.cfg b/utils/C++Tests/Clang-Code-Compile/lit.local.cfg
new file mode 100644
index 000000000000..d9e39e5d3f8d
--- /dev/null
+++ b/utils/C++Tests/Clang-Code-Compile/lit.local.cfg
@@ -0,0 +1,26 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+# testFormat: The test format to use to interpret tests.
+cxxflags = ['-D__STDC_LIMIT_MACROS',
+ '-D__STDC_CONSTANT_MACROS',
+ '-Wno-sign-compare',
+ '-I%s/include' % root.llvm_src_root,
+ '-I%s/include' % root.llvm_obj_root,
+ '-I%s/tools/clang/include' % root.llvm_src_root,
+ '-I%s/tools/clang/include' % root.llvm_obj_root]
+config.test_format = \
+ lit.formats.OneCommandPerFileTest(command=[root.clang, '-c',
+ '-o', '/dev/null'] + cxxflags,
+ dir='%s/tools/clang/lib' % root.llvm_src_root,
+ recursive=True,
+ pattern='^(.*\\.cpp)$')
+
diff --git a/utils/C++Tests/Clang-Code-Syntax/lit.local.cfg b/utils/C++Tests/Clang-Code-Syntax/lit.local.cfg
new file mode 100644
index 000000000000..8f00c8df739e
--- /dev/null
+++ b/utils/C++Tests/Clang-Code-Syntax/lit.local.cfg
@@ -0,0 +1,25 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+# testFormat: The test format to use to interpret tests.
+cxxflags = ['-D__STDC_LIMIT_MACROS',
+ '-D__STDC_CONSTANT_MACROS',
+ '-Wno-sign-compare',
+ '-I%s/include' % root.llvm_src_root,
+ '-I%s/include' % root.llvm_obj_root,
+ '-I%s/tools/clang/include' % root.llvm_src_root,
+ '-I%s/tools/clang/include' % root.llvm_obj_root]
+config.test_format = \
+ lit.formats.OneCommandPerFileTest(command=[root.clang,
+ '-fsyntax-only'] + cxxflags,
+ dir='%s/tools/clang/lib' % root.llvm_src_root,
+ recursive=True,
+ pattern='^(.*\\.cpp)$')
diff --git a/utils/C++Tests/Clang-Syntax/lit.local.cfg b/utils/C++Tests/Clang-Syntax/lit.local.cfg
new file mode 100644
index 000000000000..280d1c18a263
--- /dev/null
+++ b/utils/C++Tests/Clang-Syntax/lit.local.cfg
@@ -0,0 +1,23 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.SyntaxCheckTest(compiler=root.clang,
+ dir='%s/tools/clang/include/clang' % root.llvm_src_root,
+ recursive=True,
+ pattern='^(.*\\.h)$',
+ extra_cxx_args=['-D__STDC_LIMIT_MACROS',
+ '-D__STDC_CONSTANT_MACROS',
+ '-Wno-sign-compare',
+ '-I%s/include' % root.llvm_src_root,
+ '-I%s/include' % root.llvm_obj_root,
+ '-I%s/tools/clang/include' % root.llvm_src_root,
+ '-I%s/tools/clang/include' % root.llvm_obj_root])
diff --git a/utils/C++Tests/LLVM-Syntax/lit.local.cfg b/utils/C++Tests/LLVM-Syntax/lit.local.cfg
index 8375f0920d3d..25728bc39f47 100644
--- a/utils/C++Tests/LLVM-Syntax/lit.local.cfg
+++ b/utils/C++Tests/LLVM-Syntax/lit.local.cfg
@@ -20,4 +20,5 @@ config.test_format = lit.formats.SyntaxCheckTest(compiler=root.clang,
'-I%s/include' % root.llvm_src_root,
'-I%s/include' % root.llvm_obj_root])
-config.excludes = ['AbstractTypeUser.h']
+config.excludes = ['AbstractTypeUser.h', 'DAGISelHeader.h',
+ 'AIXDataTypesFix.h', 'Solaris.h']
diff --git a/utils/C++Tests/lit.cfg b/utils/C++Tests/lit.cfg
index a7276220209b..aa3b09d50a4c 100644
--- a/utils/C++Tests/lit.cfg
+++ b/utils/C++Tests/lit.cfg
@@ -16,3 +16,15 @@ config.suffixes = []
# Reset these from the Clang config.
config.test_source_root = config.test_exec_root = None
+
+# Don't run Clang checks by default.
+config.excludes = []
+if (not lit.params.get('run_clang_syntax') and
+ not lit.params.get('run_clang_all')):
+ config.excludes.append('Clang-Syntax')
+if (not lit.params.get('run_clang_code_syntax') and
+ not lit.params.get('run_clang_all')):
+ config.excludes.append('Clang-Code-Syntax')
+if (not lit.params.get('run_clang_compile') and
+ not lit.params.get('run_clang_all')):
+ config.excludes.append('Clang-Code-Compile')
diff --git a/utils/ccc-analyzer b/utils/ccc-analyzer
index ddc5030bc2ef..25b980057408 100755
--- a/utils/ccc-analyzer
+++ b/utils/ccc-analyzer
@@ -160,6 +160,12 @@ sub Analyze {
push @CmdArgs,"-analyzer-display-progress";
push @CmdArgs,"-analyzer-eagerly-assume";
push @CmdArgs,(split /\s/,$Analyses);
+
+ if (defined $ENV{"CCC_EXPERIMENTAL_CHECKS"}) {
+ push @CmdArgs,"-analyzer-experimental-internal-checks";
+ push @CmdArgs,"-analyzer-experimental-checks";
+ }
+
$RunAnalyzer = 1;
}
diff --git a/utils/scan-build b/utils/scan-build
index 78394b179d56..ca95676ca338 100755
--- a/utils/scan-build
+++ b/utils/scan-build
@@ -902,6 +902,8 @@ print <<ENDTEXT;
OPTIONS:
-analyze-headers - Also analyze functions in #included files.
+
+ --experimental-checks - Enable experimental checks that are currently in heavy testing
-o - Target directory for HTML report files. Subdirectories
will be created as needed to represent separate "runs" of
@@ -1097,6 +1099,12 @@ while (@ARGV) {
next;
}
+ if ($arg eq "--experimental-checks") {
+ shift @ARGV;
+ $ENV{"CCC_EXPERIMENTAL_CHECKS"} = 1;
+ next;
+ }
+
if ($arg =~ /^--use-cc(=(.+))?$/) {
shift @ARGV;
my $cc;
diff --git a/www/get_started.html b/www/get_started.html
index 86f6cef35c05..b7df928d27a8 100644
--- a/www/get_started.html
+++ b/www/get_started.html
@@ -18,24 +18,7 @@
<p>This page gives you the shortest path to checking out Clang and demos a few
options. This should get you up and running with the minimum of muss and fuss.
If you like what you see, please consider <a href="get_involved.html">getting
-involved</a> with the Clang community.</p>
-
-<h2>A Word of Warning</h2>
-
-<p>While this work aims to provide a fully functional C/C++/ObjC front-end, it
-is still relatively new and under heavy development. Currently we believe clang
-to be very usable as a C and Objective-C compiler, however there is no real C++
-support yet (this is obviously a big project). Additionally, for C and
-Objective-C:</p>
-
-<ol>
- <li>The semantic analyzer does not produce all of the warnings it should.</li>
- <li>We don't consider the API to be stable yet, and reserve the right to
- change fundamental things.</li>
- <li>Only the X86-32 and X86-64 targets have been well tested.</li>
-</ol>
-
-<p>If you run into problems, please file
+involved</a> with the Clang community. If you run into problems, please file
bugs in <a href="http://llvm.org/bugs/">LLVM Bugzilla</a> or bring up the issue
on the
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">Clang development
@@ -168,7 +151,8 @@ Visual Studio:</p>
<li>Run cmake to generate the Visual Studio solution and project files:</li>
<ul>
<li><tt>cd ..</tt> (Change directory back to the llvm top.)</li>
- <li><tt>cmake .</tt></li>
+ <li>If you are using Visual Studio 2005: <tt>cmake .</tt></li>
+ <li>Or if you are using Visual Studio 2008: <tt>cmake -G "Visual Studio 9 2008" .</tt></li>
<li>The above, if successful, will have created an LLVM.sln file in the
llvm directory.
</ul>
@@ -209,6 +193,12 @@ $ <b>./a.out</b>
hello world
</pre>
+<p>The 'clang' driver is designed to work as closely to GCC as possible to
+ maximize portability. The only major difference between the two is that
+ Clang defaults to gnu99 mode while GCC defaults to gnu89 mode. If you see
+ weird link-time errors relating to inline functions, try passing -std=gnu89
+ to clang.</p>
+
<h2>Examples of using Clang</h2>
<p>The high-level driver <tt>clang</tt> is designed to understand most of GCC's
diff --git a/www/hacking.html b/www/hacking.html
index a1833a2326c9..372d9a62ec35 100644
--- a/www/hacking.html
+++ b/www/hacking.html
@@ -127,12 +127,10 @@
<h3 id="testingWindows">Testing using Visual Studio on Windows</h3>
<!--=====================================================================-->
- <p>The cmake build tool is set up to create Visual Studio project files
- for running the tests, "clang-test" being the root.
- Unfortunately, the test runner scripts presently don't work on Windows.
- This will be fixed during the test runner revision in progress.</p>
+ <p>The Clang test suite can be run from either Visual Studio or
+ the command line.</p>
- <p>Note that the current and coming revised test runner is based on
+ <p>Note that the test runner is based on
Python, which must be installed. Find Python at:
<a href="http://www.python.org/download">http://www.python.org/download</a>.
Download the latest stable version (2.6.2 at the time of this writing).</p>
@@ -143,6 +141,62 @@
grep does work in this case.)
Get them from <a href="http://getgnuwin32.sourceforge.net">
http://getgnuwin32.sourceforge.net</a>.</p>
+
+ <p>The cmake build tool is set up to create Visual Studio project files
+ for running the tests, "clang-test" being the root. Therefore, to
+ run the test from Visual Studio, right-click the clang-test project
+ and select "Build".</p>
+
+ <p>To run all the tests from the command line, execute a command like
+ the following:</p>
+
+ <tt>
+ python (path to llvm)/llvm/utils/lit/lit.py -sv --no-progress-bar
+ (path to llvm)/llvm/tools/clang/test
+ </tt>
+
+ <p>To run a single test:</p>
+
+ <tt>
+ python (path to llvm)/llvm/utils/lit/lit.py -sv --no-progress-bar
+ (path to llvm)/llvm/tools/clang/test/(dir)/(test)
+ </tt>
+
+ <p>For example:</p>
+
+ <tt>
+ python C:/Tools/llvm/utils/lit/lit.py -sv --no-progress-bar
+ C:/Tools/llvm/tools/clang/test/Sema/wchar.c
+ </tt>
+
+ <p>The -sv option above tells the runner to show the test output if
+ any tests failed, to help you determine the cause of failure.</p>
+
+ <p>Note that a few tests currently fail on Windows. We are working to
+ correct this. Therefore your output might look something like this:</p>
+
+<tt><pre>lit.py: lit.cfg:152: note: using clang: 'C:/Tools/llvm/bin/Debug\\clang.EXE'
+lit.py: lit.cfg:157: note: using clang-cc: 'C:/Tools/llvm/bin/Debug/clang-cc.exe'
+-- Testing: 1723 tests, 2 threads --
+FAIL: Clang::(test path) (659 of 1723)
+******************** TEST 'Clang::(test path)' FAILED ********************
+Script:
+ (commands run)
+Command Output (stdout):
+ (output here)
+Command Output (stderr):
+ (output here)
+********************
+Testing Time: 83.66s
+********************
+Failing Tests (1):
+ Clang::(test path)
+ Expected Passes : 1704
+ Expected Failures : 18
+ Unexpected Failures: 1
+</pre></tt>
+
+ <p>The last statistic, "Unexpected Failures", is the important one.</p>
<!--=====================================================================-->
<h2 id="patches">Creating Patch Files</h2>